分享
 
 
 

Bjarne:为什么不能为模板参数定义约束?

王朝java/jsp·作者佚名  2008-06-01
窄屏简体版  字體: |||超大  

可以的,而且方法非常简单和通用。

看看这个:

template<class Container>

void draw_all(Container& c)

{

for_each(c.begin(),c.end(),mem_fun(&Shape::draw));

}

假如出现类型错误,可能是发生在相当复杂的for_each()调用时。例如,假如容器的元素类型是int,我们将得到一个和for_each()相关的含义模糊的错误(因为不能够对对一个int值调用Shape::draw的方法)。

为了提前捕捉这个错误,我这样写:

template<class Container>

void draw_all(Container& c)

{

Shape* p = c.front(); // accept only containers of Shape*s

for_each(c.begin(),c.end(),mem_fun(&Shape::draw));

}

对于现在的大多数编译器,中间变量p的初始化将会触发一个易于了解的错误。这个窍门在很多语言中都是通用的,而且在所有的标准创建中都必须这样做。在成品的代码中,我也许可以这样写:

template<class Container>

void draw_all(Container& c)

{

typedef typename Container::value_type T;

Can_copy<T,Shape*>(); // accept containers of only Shape*s

for_each(c.begin(),c.end(),mem_fun(&Shape::draw));

}

这样就很清楚了,我在建立一个断言(assertion)。Can_copy模板可以这样定义:

template<class T1, class T2> strUCt Can_copy {

static void constraints(T1 a, T2 b) { T2 c = a; b = a; }

Can_copy() { void(*p)(T1,T2) = constraints; }

};

Can_copy(在运行时)检查T1是否可以被赋值给T2。Can_copy<T,Shape*>检查T是否是Shape*类型,或者是一个指向由Shape类公共继续而来的类的对象的指针,或者是被用户转换到Shape*类型的某个类型。注重这个定义被精简到了最小:

一行命名要检查的约束,和要检查的类型

一行列出指定的要检查的约束(constraints()函数)

一行提供触发检查的方法(通过构造函数)

注重这个定义有相当合理的性质:

你可以表达一个约束,而不用声明或复制变量,因此约束的编写者可以用不着去设想变量如何被初始化,对象是否能够被复制,被销毁,以及诸如此类的事情。(当然,约束要检查这些属性的情况时例外。)

使用现在的编译器,不需要为约束产生代码

定义和使用约束,不需要使用宏

当约束失败时,编译器会给出可接受的错误信息,包括“constraints”这个词(给用户一个线索),约束的名字,以及导致约束失败的具体错误(例如“无法用double*初始化Shape*”)。

那么,在C++语言中,有没有类似于Can_copy——或者更好——的东西呢?在《C++语言的设计和演变》中,对于在C++中实现这种通用约束的困难进行了分析。从那以来,出现了很多方法,来让约束类变得更加轻易编写,同时仍然能触发良好的错误信息。例如,我信任我在Can_copy中使用的函数指针的方式,它源自Alex Stepanov和Jeremy Siek。我并不认为Can_copy()已经可以标准化了——它需要更多的使用。同样,在C++社区中,各种不同的约束方式被使用;到底是哪一种约束模板在广泛的使用中被证实是最有效的,还没有达成一致的意见。

但是,这种方式非常普遍,比语言提供的专门用于约束检查的机制更加普遍。无论如何,当我们编写一个模板时,我们拥有了C++提供的最丰富的表达力量。看看这个:

template<class T, class B> struct Derived_from {

static void constraints(T* p) { B* pb = p; }

Derived_from() { void(*p)(T*) = constraints; }

};

template<class T1, class T2> struct Can_copy {

static void constraints(T1 a, T2 b) { T2 c = a; b = a; }

Can_copy() { void(*p)(T1,T2) = constraints; }

};

template<class T1, class T2 = T1> struct Can_compare {

static void constraints(T1 a, T2 b) { a==b; a!=b; a<b; }

Can_compare() { void(*p)(T1,T2) = constraints; }

};

template<class T1, class T2, class T3 = T1> struct Can_multiply {

static void constraints(T1 a, T2 b, T3 c) { c = a*b; }

Can_multiply() { void(*p)(T1,T2,T3) = constraints; }

};

struct B { };

struct D : B { };

struct DD : D { };

struct X { };

int main()

{

Derived_from<D,B>();

Derived_from<DD,B>();

Derived_from<X,B>();

Derived_from<int,B>();

Derived_from<X,int>();

Can_compare<int,float>();

Can_compare<X,B>();

Can_multiply<int,float>();

Can_multiply<int,float,double>();

Can_multiply<B,X>();

Can_copy<D*,B*>();

Can_copy<D,B*>();

Can_copy<int,B*>();

}

// 典型的“元素必须继续自Mybase*”约束:

template<class T> class Container : Derived_from<T,Mybase> {

// ...

};

事实上,Derived_from并不检查来源(derivation),而仅仅检查转换(conversion),不过这往往是一个更好的约束。为约束想一个好名字是很难的。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有