STL笔记:traits编程
最近在看stl源码剖析,其中遇到了traits技术,感觉很有意思,在此记录下来。
故事的开端是这样的,想实现一个函数,想让这个函数对其参数的类型做出相应的行为,而不是参数具体的值。比如,如果我想实现一个函数func(t),当参数t属于内置类型时,打印“I'm here”,当参数t属于自己已经定义或未来可能定义的类类型的类型时,打印“I'm not here”,该怎么实现它呢?也许函数重载是一种方法,不过对于每个类型都重载一次未免工作量有些偏大,而且当定义新的class时,还得为这个新添加的class再次定义一次func。
利用模板是一种不错的选择。不过对于模板来说,如何去实现不同的类型有不同的行为呢?可以注意到的是,类型也许有无限多,但行为只有有限的几种,在这里只有两种行为:打印“I'm here”和打印“I'm not here”。于是问题就变为了,对于模板,如何去实现一种分派机制,当类型属于内置类型时,将其分派到实现打印"I'm here"的函数,当类型属于类类型时,将其分派到实现打印"I'm not here"的函数。
用代码来描述问题的解决方案。首先定义了实现打印行为的两个函数,这里使用的函数重载作为函数名的统一,同时定义了两个无成员的类,分别作为两个函数的参数,从而实现重载:
1 struct true_flag{}; 2 struct flase_flag{}; 3 4 void func_flag(true_flag t){cout<<"I'm here";} 5 void func_flag(false_flag f){cout<<"I'm not here";}
然后实现作为类型分派的traits模板类,用于将已定义或未来可能定义的类分派到func(false_flag)那里:
1 template<class T> 2 class traits{ 3 typedef false_flag is_flag; 4 };
对于内置类型,对traits进行特化,比如int和char:
template<> traits<int>{ typedef true_flag is_flag; }; template<> traits<char>{ typedef true_flag is_flag; };
下面实现了func函数:
template<class T> void func(T t){ typedef typename traits<T>::is_flag is_flag; func_traits(is_flag()); }
对于自定义的类类型,is_flag将对应false_flag类,而对于内置类型int或者char,is_flag将对应true_flag。这样便实现了对不同的类型自动调用了不同的打印函数。
下面是测试完整的测试代码:
1 #include<iostream> 2 using namespace std; 3 4 struct true_flag{}; 5 struct false_flag{}; 6 7 void func_traits(true_flag t){cout<<"I'm here"<<endl;} 8 9 void func_traits(false_flag f){cout<<"I'm not here"<<endl;} 10 11 template<class T> 12 struct traits{ 13 typedef false_flag is_flag; 14 }; 15 16 template<> 17 struct traits<int>{ 18 typedef true_flag is_flag; 19 }; 20 21 template<class T> 22 void func(T t){ 23 typedef typename traits<T>::is_flag is_flag; 24 func_traits(is_flag()); 25 } 26 27 struct test{}; 28 29 int main(){ 30 test t; 31 func(t); 32 int i; 33 func(i); 34 }
运行结果如下:

浙公网安备 33010602011771号