免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3089 | 回复: 10
打印 上一主题 下一主题

[C++] 请问这个模版怎么特化? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-04-20 00:46 |只看该作者 |倒序浏览
本帖最后由 Frahm 于 2013-04-20 00:56 编辑
  1. template<typename Iterator>
  2. struct iterator_traits {
  3.   typedef Iterator iterator;
  4.   typedef typename Iterator::iterator_category iterator_category;
  5.   typedef typename Iterator::value_type value_type;
  6.   typedef typename Iterator::difference_type difference_type;
  7.   typedef typename Iterator::pointer pointer;
  8.   typedef typename Iterator::reference reference;
  9. //other non-standard traits
  10. };
  11. //这样特化不行,说是不能推导出类型或者有未使用参数
  12. template<typename T, typename Alloc>
  13. struct iterator_traits<typename std::vector<T, Alloc>::iterator> {
  14.   typedef typename std::vector<T, Alloc>::iterator iterator;
  15.   typedef typename iterator::iterator_category iterator_category;
  16.   typedef typename iterator::value_type value_type;
  17.   typedef typename iterator::difference difference_type;
  18.   typedef typename iterator::pointer pointer;
  19.   typedef typename iterator::reference reference;
  20.   //...other non-standard traits
  21. };
复制代码
我想把iterator_traits根据stl中的容器来特化,比如std::vector, 该怎么做呢?

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
2 [报告]
发表于 2013-04-20 08:17 |只看该作者
这种设计本身就不合理,应该根据迭代器的类型(比如 前向、随机 等等)来

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
3 [报告]
发表于 2013-04-20 08:44 |只看该作者
你这不是特化,特化要提供具体的类型的,你整个代码里全是模板类型。
你应该是声明一个继承自原来模板的新模板,这样:
template<typename T, typename Alloc>
struct my_iterator_traits : public iterator_traits<typename std::vector<T, Alloc>::iterator> {
  typedef typename std::vector<T, Alloc>::iterator iterator;
  typedef typename iterator::iterator_category iterator_category;
  typedef typename iterator::value_type value_type;
  typedef typename iterator::difference difference_type;
  typedef typename iterator::pointer pointer;
  typedef typename iterator::reference reference;
  //...other non-standard traits
  //在这里面重载基类模板的方法就可以了
};

//使用的时候这样
my_iterator_traits<T, Alloc> it;

论坛徽章:
0
4 [报告]
发表于 2013-04-21 00:17 |只看该作者
回复 2# bruceteen


    我的目的是在原本iterator_category的基础上扩展,但为了一致性,又不能在std内部定义类型,所以我打算重写这个iterator_traits, 和所有的iterator category tag, 但为了兼容原本的stl 容器,所以我打算根据所有的stl容器来特化我的iterator_traits

论坛徽章:
0
5 [报告]
发表于 2013-04-21 00:27 |只看该作者
回复 3# csumck


    这样的话,调用接口就不一致了,我以为可以自动推导的

论坛徽章:
0
6 [报告]
发表于 2013-04-21 00:56 |只看该作者
回复 3# csumck
奇怪的是我这样写就可以推导出来
  1. template<typename T, typename Alloc>
  2. struct iterator_traits<std::vector<T, Alloc> > {
  3.   typedef typename std::vector<T, Alloc>::iterator iterator;
  4.   typedef typename iterator::iterator_category iterator_category;
  5.   typedef typename iterator::value_type value_type;
  6.   typedef typename iterator::difference_type difference_type;
  7.   typedef typename iterator::pointer pointer;
  8.   typedef typename iterator::reference reference;
  9.   //...other non-standard traits
  10. };
复制代码
iterator_traits<std::vector<int> > mty; //这样可以
不过显然,接受的参数不对了
我感觉是typename的问题,但在这里要引出其iterator类型的话不加typename又不行,很矛盾啊

论坛徽章:
0
7 [报告]
发表于 2013-04-21 01:57 |只看该作者
本帖最后由 Frahm 于 2013-04-21 01:58 编辑

我明白问题了,不能根据iterator推导出vector类型,因为iterator是模版中的参数,可能是任何类型,比如int*, 此时仅根据iterator类型无法断定vector类型,可能根本不存在该vector类型。所以结论就是模版特化的时候特化模版参数的类型不能是由一个类型引出(:: )的类型,简单的说就是不能有typename,否则相当于反向推导,无法判别。

论坛徽章:
0
8 [报告]
发表于 2013-04-21 02:00 |只看该作者
那么现在的问题是,我该怎么实现特化呢?如何知道一个Iterator是属于哪个Container的呢?

论坛徽章:
0
9 [报告]
发表于 2013-04-21 09:06 |只看该作者
我知道了,突然想到,这样就可以了

  1. struct my_input_iterator_tag : public std::input_iterator_tag {};
  2. struct my_output_iterator_tag : public std::output_iterator_tag {};

  3. struct my_forward_iterator_tag
  4.   : public std::forward_iterator_tag {};

  5. struct my_bidirecitional_iterator_tag
  6.   : public std::bidirectional_iterator_tag {};

  7. struct my_random_access_iterator_tag
  8.   : public std::random_access_iterator_tag {};


  9. template<typename Iterator>
  10. struct iterator_traits {
  11.   typedef typename Iterator::iterator_category iterator_category;
  12.   typedef typename Iterator::value_type value_type;
  13.   typedef typename Iterator::difference_type difference_type;
  14.   typedef typename Iterator::pointer pointer;
  15.   typedef typename Iterator::reference reference;
  16. };
复制代码
这样就可以兼容stl的容器,而且可以自己拓展iterator category了。

论坛徽章:
44
15-16赛季CBA联赛之浙江
日期:2021-10-11 02:03:59程序设计版块每日发帖之星
日期:2016-07-02 06:20:0015-16赛季CBA联赛之新疆
日期:2016-04-25 10:55:452016科比退役纪念章
日期:2016-04-23 00:51:2315-16赛季CBA联赛之山东
日期:2016-04-17 12:00:2815-16赛季CBA联赛之福建
日期:2016-04-12 15:21:2915-16赛季CBA联赛之辽宁
日期:2016-03-24 21:38:2715-16赛季CBA联赛之福建
日期:2016-03-18 12:13:4015-16赛季CBA联赛之佛山
日期:2016-02-05 00:55:2015-16赛季CBA联赛之佛山
日期:2016-02-04 21:11:3615-16赛季CBA联赛之天津
日期:2016-11-02 00:33:1215-16赛季CBA联赛之浙江
日期:2017-01-13 01:31:49
10 [报告]
发表于 2013-04-21 11:05 |只看该作者
回复 7# Frahm

这个当然不行啦,比如说:

  1. struct MyStruct {
  2.     typedef int some_type;
  3. };

  4. template<typename T>
  5. struct some_template{ ... };

  6. template<typename T>
  7. struct some_template<T::some_type>{ ... };
复制代码
万一你用MyStruct::some_type去规约,可这个type实际上就是int,编译器怎么知道T应该是什么?

最主要的问题就是一个type里面定义的type,和外面的type不存在关系,这种东西叫non-dedecued context

C++在这些地方就是一个大坑,没事表往里跳
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP