羌塘之风

重剑无锋,大巧不工。

导航

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 }
View Code

  运行结果如下:

 

posted on 2013-11-07 17:40  羌塘之风  阅读(194)  评论(0)    收藏  举报