posts - 18,  comments - 104,  trackbacks - 0
先看看boost的实现吧。

 1 template<typename _T>
 2 struct wapper
 3 {};
 4 template <typename _T>
 5 _T&(* fun1(wapper<_T> t))();
 6 true_type fun1();
 7 
 8 class true_type{};
 9 class false_type
10 {
11     char c[8];
12 };
13 
14 template<typename _T>
15 true_type fun2(_T&(*)());
16 false_type fun2();
17 
18 template<typename _T>
19 struct is_reference
20 {
21     static const bool value = sizeof(fun2(fun1(wapper<_T>()))) == sizeof(false_type);
22 };


就是上面这个样子,我做了一下简化,更容易理解。

下面是我的实现版本,最后再解释。

 1 template<typename _T>
 2 class is_reference
 3 {
 4     template<typename _T>
 5     struct wapper
 6     {};
 7 
 8     class true_type{};
 9     class false_type
10     {
11         char c[8];
12     };
13 
14     template <typename _T>
15     static _T& fun1(wapper<_T>);
16     static true_type fun1();
17 
18     template<typename _T>
19     static true_type fun2(_T);
20     static false_type fun2(true_type);
21 public:
22     static const bool value = sizeof(fun2(fun1(wapper<_T>()))) == sizeof(false_type);
23 };

用法如下:

1 bool res1 = is_reference<char>::value;   //res1 == false
2 bool res2 = is_reference<char&>::value;  //res2 == true

函数参数会自动去掉引用比如:
template<_T> void fun(_T a);
无论任何时候,_T总是非引用类型。

但是不让函数通过函数参数直接推导模板参数的类型,就给函数参数加一个间接层wapper,
类模板不会自动去掉引用,所以配合函数模板可以保证得到原来的类型。
 
template<_T> void fun(wapper<_T> a);
这时候,_T 就可能是引用类型了。因为c++不支持引用的引用,当模板函数中要用到引用的引用的时候,模板函数就会推导失败。
即,只要在函数fun的参数或者返回值里面含有_T&的话,fun就会推导失败。从而编译器会选择 true_type fun(...);
由于参数已经被用于推导模板参数,所以只能在返回类型中含有_T&,从而利用函数重载而区分引用和非引用。
如果直接返回_T&类型,后面必须要定义只接受true_type类型参数的函数进行区分,因为_T&肯定是引用类型,所以后面接受
false_type fun2(true_type)的函数会被选择。

但是遇到is_reference<true_type>::value怎么办,我把他们都放到私有域了,永远不会看到的,搞定。
boost::trait中返回函数指针的解法也OK。因为char永远不可能成功匹配函数指针。

此方法的关键在于编译器选择重载函数的先后顺序。
而boost::trait中的方法是char永远不能转化成一个函数指针,从而选择不同重载版本。

解释完毕。
posted on 2009-02-20 21:44 尹东斐 阅读(2085) 评论(5)  编辑 收藏 引用

FeedBack:
# re: boost::trait::is_reference 的研究与修改
2009-02-20 21:48 | 发生地方
不错,不错  回复  更多评论
  
# re: boost::trait::is_reference 的研究与修改[未登录]
2009-02-21 09:27 | jans2002
高手,总觉得模板很玄乎,也没有好的调试手段  回复  更多评论
  
# re: boost::trait::is_reference 的研究与修改
2009-02-21 10:35 | 尹东斐
@jans2002

模板现在是不好调试,不过好像VC 10的 intellisence 会有帮助吧。 还没有用过。

我目前的水平主要还是自己推,不知道大牛们玩模板是不是和咱写程序一样轻松。。。  回复  更多评论
  
# re: boost::trait::is_reference 的研究與修改
2009-04-21 12:10 | SL
為何要過濾true_type?
true_type 一樣是個 type, 似乎沒有必要如此.

  回复  更多评论
  
# re: boost::trait::is_reference 的研究与修改
2009-04-21 23:24 | yindf
@SL

is_reference<true_type>::value
被使用时,fun1的第一个版本会被选择,因为T被推导成true_type,所以最终结果是is_reference<true_type>::value == true,这是不对的。  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2009年2月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
1234567

常用链接

留言簿(4)

随笔档案

文章分类

文章档案

相册

好友博客

搜索

  •  

最新评论

阅读排行榜

评论排行榜