模板别名

来源:互联网 发布:华彩软件下载站 编辑:程序博客网 时间:2024/05/01 14:06
我有一个模板
C/C++ code
?
1
2
3
4
5
6
template<class T>           //1
class A : public LT         //2
{
public:
  typedef list<T> LT;       //3
};

这是一个我要写的类的一个简化版本,实际1处模板参数也不止一个,3处的LT是一个很复杂的类型定义,是由一系列typedef最后得到的一个typedef(与T有关)
如果我像上面这么写,编译时会报LT未定义。可是我又不能把3放到类外面,因为LT与模板参数T有关。我目前能想到的就是LT老老实实按照没有typedef之前的形式写。
不知道大家有没好办法,保留上述这种简洁的定义方式,又能让编译通过?
  • <iframe id="iframeu1636200_0" src="http://pos.baidu.com/icym?rdid=1636200&amp;dc=2&amp;di=u1636200&amp;dri=0&amp;dis=0&amp;dai=2&amp;ps=1021x662&amp;dcb=BAIDU_SSP_define&amp;dtm=BAIDU_DUP_SETJSONADSLOT&amp;dvi=0.0&amp;dci=-1&amp;dpt=none&amp;tsr=0&amp;tpr=1461732152650&amp;ti=%E6%A8%A1%E6%9D%BF%E5%8F%82%E6%95%B0%E7%9A%84%E4%B8%80%E4%B8%AAtypedef%E4%BD%9C%E4%B8%BA%E8%AF%A5%E6%A8%A1%E6%9D%BF%E7%B1%BB%E7%9A%84%E5%9F%BA%E7%B1%BB-CSDN%E8%AE%BA%E5%9D%9B-CSDN.NET-%E4%B8%AD%E5%9B%BD%E6%9C%80%E5%A4%A7%E7%9A%84IT%E6%8A%80%E6%9C%AF%E7%A4%BE%E5%8C%BA&amp;ari=1&amp;dbv=2&amp;drs=3&amp;pcs=1903x952&amp;pss=1903x10349&amp;cfv=18&amp;cpl=42&amp;chi=1&amp;cce=true&amp;cec=UTF-8&amp;tlm=1461732152&amp;ltu=http%3A%2F%2Fbbs.csdn.net%2Ftopics%2F390609962%3Fpage%3D1&amp;ltr=http%3A%2F%2Fwww.baidu.com%2Fs%3Fword%3Dtemplate%2Baliases%26tn%3Dsitehao123_pg%26ie%3Dutf-8&amp;ecd=1&amp;psr=1920x1080&amp;par=1920x1040&amp;pis=-1x-1&amp;ccd=24&amp;cja=true&amp;cmi=102&amp;col=zh-CN&amp;cdo=-1&amp;tcn=1461732153&amp;qn=5515b3b448d520d2&amp;tt=1461732152632.25.235.235" width="200" height="22" align="center,center" vspace="0" hspace="0" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true" style="box-sizing: content-box; border-width: 0px; vertical-align: bottom; margin: 0px;"></iframe>
     
  • <iframe id="iframeu1636201_0" src="http://pos.baidu.com/icym?rdid=1636201&amp;dc=2&amp;di=u1636201&amp;dri=0&amp;dis=0&amp;dai=3&amp;ps=1021x916&amp;dcb=BAIDU_SSP_define&amp;dtm=BAIDU_DUP_SETJSONADSLOT&amp;dvi=0.0&amp;dci=-1&amp;dpt=none&amp;tsr=0&amp;tpr=1461732152650&amp;ti=%E6%A8%A1%E6%9D%BF%E5%8F%82%E6%95%B0%E7%9A%84%E4%B8%80%E4%B8%AAtypedef%E4%BD%9C%E4%B8%BA%E8%AF%A5%E6%A8%A1%E6%9D%BF%E7%B1%BB%E7%9A%84%E5%9F%BA%E7%B1%BB-CSDN%E8%AE%BA%E5%9D%9B-CSDN.NET-%E4%B8%AD%E5%9B%BD%E6%9C%80%E5%A4%A7%E7%9A%84IT%E6%8A%80%E6%9C%AF%E7%A4%BE%E5%8C%BA&amp;ari=1&amp;dbv=2&amp;drs=3&amp;pcs=1903x952&amp;pss=1903x10349&amp;cfv=18&amp;cpl=42&amp;chi=1&amp;cce=true&amp;cec=UTF-8&amp;tlm=1461732152&amp;ltu=http%3A%2F%2Fbbs.csdn.net%2Ftopics%2F390609962%3Fpage%3D1&amp;ltr=http%3A%2F%2Fwww.baidu.com%2Fs%3Fword%3Dtemplate%2Baliases%26tn%3Dsitehao123_pg%26ie%3Dutf-8&amp;ecd=1&amp;psr=1920x1080&amp;par=1920x1040&amp;pis=-1x-1&amp;ccd=24&amp;cja=true&amp;cmi=102&amp;col=zh-CN&amp;cdo=-1&amp;tcn=1461732153&amp;qn=fea29928bb536beb&amp;tt=1461732152632.31.238.238" width="200" height="22" align="center,center" vspace="0" hspace="0" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true" style="box-sizing: content-box; border-width: 0px; vertical-align: bottom; margin: 0px;"></iframe>
     
  • <iframe id="iframeu1636204_0" src="http://pos.baidu.com/icym?rdid=1636204&amp;dc=2&amp;di=u1636204&amp;dri=0&amp;dis=0&amp;dai=4&amp;ps=1021x1170&amp;dcb=BAIDU_SSP_define&amp;dtm=BAIDU_DUP_SETJSONADSLOT&amp;dvi=0.0&amp;dci=-1&amp;dpt=none&amp;tsr=0&amp;tpr=1461732152650&amp;ti=%E6%A8%A1%E6%9D%BF%E5%8F%82%E6%95%B0%E7%9A%84%E4%B8%80%E4%B8%AAtypedef%E4%BD%9C%E4%B8%BA%E8%AF%A5%E6%A8%A1%E6%9D%BF%E7%B1%BB%E7%9A%84%E5%9F%BA%E7%B1%BB-CSDN%E8%AE%BA%E5%9D%9B-CSDN.NET-%E4%B8%AD%E5%9B%BD%E6%9C%80%E5%A4%A7%E7%9A%84IT%E6%8A%80%E6%9C%AF%E7%A4%BE%E5%8C%BA&amp;ari=1&amp;dbv=2&amp;drs=3&amp;pcs=1903x952&amp;pss=1903x10349&amp;cfv=18&amp;cpl=42&amp;chi=1&amp;cce=true&amp;cec=UTF-8&amp;tlm=1461732152&amp;ltu=http%3A%2F%2Fbbs.csdn.net%2Ftopics%2F390609962%3Fpage%3D1&amp;ltr=http%3A%2F%2Fwww.baidu.com%2Fs%3Fword%3Dtemplate%2Baliases%26tn%3Dsitehao123_pg%26ie%3Dutf-8&amp;ecd=1&amp;psr=1920x1080&amp;par=1920x1040&amp;pis=-1x-1&amp;ccd=24&amp;cja=true&amp;cmi=102&amp;col=zh-CN&amp;cdo=-1&amp;tcn=1461732153&amp;qn=a93af8c901311070&amp;tt=1461732152632.32.224.227" width="200" height="22" align="center,center" vspace="0" hspace="0" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" allowtransparency="true" style="box-sizing: content-box; border-width: 0px; vertical-align: bottom; margin: 0px;"></iframe>
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    回复次数:23
    #1 得分:0回复于: 2013-10-09 16:19:50
    这是我在编写ATL项目时遇到的一个问题,ATL项目中的类定义摘录如下:
    C/C++ code
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    template<class IChl, class Ctl, class ChlSmp, class SnsSmp, class Sns>
    class IChunnelImp : public IChl, public ISensorsCollImpl
    {
    public:
        typedef typename list<CAdapt<CComObjectPtr<Sns>>> SensorContainer;
        typedef typename CComEnumOnSTL<IEnumVARIANT, &IID_IEnumVARIANT, VARIANT, 
                        _CopyVariantFromAdaptComObjectPtr<Sns>, 
                        SensorContainer>
                CComEnumVariantOnListOfSensors;
        typedef typename ICollectionOnSTLImpl<
                        IDispatchImpl<IChunnel, &IID_IChunnel, &LIBID_TroikaLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
                        SensorContainer,
                        ISensor*, 
                        _CopyItfFromAdaptComObjectPtr<ISensor, Sns>,
                        CComEnumVariantOnListOfSensors>
                ISensorsCollImpl;
    //...
    };

    这是一个集合的实现,大家可以看到ISensorsCollImpl是由3个typedef最后才得到的,并且他是IChunnelImp的基类,其结构就像问题中的简化例子一样。
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #2 得分:0回复于: 2013-10-09 16:44:27
    C++11的模板别名可以解决你的问题。

    temple< typename T >
    using ……
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #3 得分:0回复于: 2013-10-09 17:25:04
    伤心,这是在VS2005中,好像没有类型别名吧?
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #4 得分:15回复于: 2013-10-09 17:57:34
    C/C++ code
    ?
    1
    2
    3
    4
    5
    6
    template<class T>
    class LTT
    {
    public:
      typedef list<T> type;
    };


    C/C++ code
    ?
    1
    2
    3
    4
    template<class T>           //1
    class A : public typename LTT<T>::type         //2
    {
    };
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #5 得分:0回复于: 2013-10-09 20:39:11
    就别想着偷懒呗。
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #6 得分:0回复于: 2013-10-10 09:30:39
    引用 4 楼 Saleayas 的回复:
    C/C++ code
    ?
    1
    2
    3
    4
    5
    6
    template<class T>
    class LTT
    {
    public:
      typedef list<T> type;
    };


    C/C++ code
    ?
    1
    2
    3
    4
    template<class T>           //1
    class A : public typename LTT<T>::type         //2
    {
    };
    按照Saleayas的方法,可以达到我要的效果,谢谢。
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #7 得分:0回复于: 2013-10-10 09:31:38
    引用 5 楼 taodm 的回复:
    就别想着偷懒呗。
    呵呵,程序员都喜欢偷懒。
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #8 得分:0回复于: 2013-10-10 09:49:40
    引用 4 楼 Saleayas 的回复:
    C/C++ code
    ?
    1
    2
    3
    4
    5
    6
    template<class T>
    class LTT
    {
    public:
      typedef list<T> type;
    };


    C/C++ code
    ?
    1
    2
    3
    4
    template<class T>           //1
    class A : public typename LTT<T>::type         //2
    {
    };

    type traits. +1
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #9 得分:0回复于: 2013-10-10 10:38:39
    就是traits
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #10 得分:0回复于: 2013-10-10 13:00:35
    4楼的方法是不被推荐的,在没有模板别名的C++03,传统上就如四楼那样用一个类去代替typedef,问题是这个类其实是冗余的,它仅仅为了某些并非必要的语法便利而成为一个无用的替代物。因为这个缘故,C++11才提出了模板别名来代替这种方式。

    楼主懂得使用VS2005,难道使用VS2010或者VS2012会成为一件很困难的事情么??
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #11 得分:0回复于: 2013-10-10 14:32:05
    引用 10 楼 supermegaboy 的回复:
    4楼的方法是不被推荐的,在没有模板别名的C++03,传统上就如四楼那样用一个类去代替typedef,问题是这个类其实是冗余的,它仅仅为了某些并非必要的语法便利而成为一个无用的替代物。因为这个缘故,C++11才提出了模板别名来代替这种方式。

    楼主懂得使用VS2005,难道使用VS2010或者VS2012会成为一件很困难的事情么??
    你经验丰富,一定明白换不换编译器全看PM的脸色
    而当上PM后,很多人都不再继续专研技术了
    只要老方法还能够用,就不要改变也不求改进
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #12 得分:5回复于: 2013-10-10 14:44:31
    那试试这样呢,虽然也不是太好看吧,不过暂时避免了 #10 说的问题,而且也不需要 c++11 的特性。
    C/C++ code
    ?
    1
    2
    3
    4
    template<class T, typename LT = std::list<T>>
    class A : public LT
    {
    };
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #13 得分:0回复于: 2013-10-10 14:56:48
    我好像记得 VS 2012 也不支持 template aliases 的
    当时,我测试过 C++11 新支持的东西。
    可以就是不支持模板别名和变参模板。

    不过 VS 2013 完美支持了。
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #14 得分:0回复于: 2013-10-10 14:58:40
    很多开发时多是团队开发,
    而在一个团队里面,是有人不希望随便更换编译器的。

    所以,一个团队换编译器是很麻烦的。
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #15 得分:0回复于: 2013-10-10 18:10:16
    真是可恶,2010和2012均未提供模板别名,2013 RTM才开始支持,g++早就有了。一向不喜欢微软的C/C++编译器,只是很多时候又不得不使用它们,无奈。
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #16 得分:0回复于: 2013-10-10 18:14:55
    引用 12 楼 ri_aje 的回复:
    那试试这样呢,虽然也不是太好看吧,不过暂时避免了 #10 说的问题,而且也不需要 c++11 的特性。
    C/C++ code
    ?
    1
    2
    3
    4
    template<class T, typename LT = std::list<T>>
    class A : public LT
    {
    };

    你这个做法其实跟四楼是一样的(称为元函数转发),好处就是少写个type,但本质一样。

    MPL经常使用元函数转发简化代码。
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #17 得分:0回复于: 2013-10-10 18:22:09
    引用 11 楼 stereoMatching 的回复:
    楼主懂得使用VS2005,难道使用VS2010或者VS2012会成为一件很困难的事情么??
    你经验丰富,一定明白换不换编译器全看PM的脸色
    而当上PM后,很多人都不再继续专研技术了
    只要老方法还能够用,就不要改变也不求改进


    引用 14 楼 Saleayas 的回复:
    很多开发时多是团队开发,
    而在一个团队里面,是有人不希望随便更换编译器的。

    所以,一个团队换编译器是很麻烦的。

    这个不一定的,信息项目的特点就是需求变化频繁,编译器选择就是配置管理中的一项内容,同时在风险控制中需要加以考虑并拟定补救措施。
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #18 得分:0回复于: 2013-10-10 18:42:50
    引用 13 楼 Saleayas 的回复:
    我好像记得 VS 2012 也不支持 template aliases 的
    当时,我测试过 C++11 新支持的东西。
    可以就是不支持模板别名和变参模板。

    不过 VS 2013 完美支持了。
    并不完美
    目前测试的结果,类似这种仍然没有支持:
    template < typename _Ty > using MyPtr = _Ty *; //既非类结构也非函数,但是却合法
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #19 得分:0回复于: 2013-10-10 23:40:37
    引用 16 楼 supermegaboy 的回复:
    Quote: 引用 12 楼 ri_aje 的回复:
     那试试这样呢,虽然也不是太好看吧,不过暂时避免了 #10 说的问题,而且也不需要 c++11 的特性。
    C/C++ code
    ?
    1
    2
    3
    4
    template<class T, typename LT = std::list<T>>
    class A : public LT
    {
    };

    你这个做法其实跟四楼是一样的(称为元函数转发),好处就是少写个type,但本质一样。

    MPL经常使用元函数转发简化代码。
    我觉得楼主就是不想同样的东西打两遍。
    你说的 using 的那个方法,其实我也没理解怎么避免多次重复打字,并且不引入冗余名称,要不你秀秀代码?
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #20 得分:0回复于: 2013-10-11 00:00:53
    never mind, I think I got it.
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #21 得分:0回复于: 2013-10-11 04:30:54
    引用 19 楼 ri_aje 的回复:
    Quote: 引用 16 楼 supermegaboy 的回复:
    Quote: 引用 12 楼 ri_aje 的回复:
     那试试这样呢,虽然也不是太好看吧,不过暂时避免了 #10 说的问题,而且也不需要 c++11 的特性。
    C/C++ code
    ?
    1
    2
    3
    4
    template<class T, typename LT = std::list<T>>
    class A : public LT
    {
    };

    你这个做法其实跟四楼是一样的(称为元函数转发),好处就是少写个type,但本质一样。

    MPL经常使用元函数转发简化代码。
    我觉得楼主就是不想同样的东西打两遍。
    你说的 using 的那个方法,其实我也没理解怎么避免多次重复打字,并且不引入冗余名称,要不你秀秀代码?

    这不是打几遍的问题,毕竟是拷贝黏贴就可以做到的,就省那么几个字又没谁会给好处。
    关键是维护问题。如果某个定义字数很长很复杂。以后再改动的时候就可能出现没有同步修改的情况。毕竟到那时候再看代码可能根本不记得这个代码应该和另一个是一起的,可能还以为只是个单独的表达式了。
    至于有没有更好的方法,目前本人也还没发现,谁有方法倒是可以说一下。
    template<class T, typename LT = std::list<T>>
    class A : public LT
    这方法真的不行。因为这样的话并不符合lz那种强制性的绑定约束
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #22 得分:0回复于: 2013-10-11 10:21:51
    引用 21 楼 unituniverse2 的回复:
    Quote: 引用 19 楼 ri_aje 的回复:
    Quote: 引用 16 楼 supermegaboy 的回复:
    Quote: 引用 12 楼 ri_aje 的回复:
     那试试这样呢,虽然也不是太好看吧,不过暂时避免了 #10 说的问题,而且也不需要 c++11 的特性。
    C/C++ code
    ?
    1
    2
    3
    4
    template<class T, typename LT = std::list<T>>
    class A : public LT
    {
    };

    你这个做法其实跟四楼是一样的(称为元函数转发),好处就是少写个type,但本质一样。

    MPL经常使用元函数转发简化代码。
    我觉得楼主就是不想同样的东西打两遍。
    你说的 using 的那个方法,其实我也没理解怎么避免多次重复打字,并且不引入冗余名称,要不你秀秀代码?

    这不是打几遍的问题,毕竟是拷贝黏贴就可以做到的,就省那么几个字又没谁会给好处。
    关键是维护问题。如果某个定义字数很长很复杂。以后再改动的时候就可能出现没有同步修改的情况。毕竟到那时候再看代码可能根本不记得这个代码应该和另一个是一起的,可能还以为只是个单独的表达式了。
    至于有没有更好的方法,目前本人也还没发现,谁有方法倒是可以说一下。
    template<class T, typename LT = std::list<T>>
    class A : public LT
    这方法真的不行。因为这样的话并不符合lz那种强制性的绑定约束
    同意你前半截的理论。
    至于你说默认模板参数"不符合lz那种强制性的绑定约束",我不理解。
    什么叫“强制性的绑定约束”?
    LT 在类作用域内部已经是通用的了,还那里需要导致代码重复,以至于“再看代码可能根本不记得这个代码应该和另一个是一起的”?
    唯一造成问题的就是 LT 需要在类外使用,这样的话可能导致重复,然后导致维护问题。
    解决方案可以用 traits 或类似的技术,比如类内定义类型,然后所有其他地方都通过类的 qualified 名称访问。
    也可以用 using,但和 traits 本质是一样的。
    反正我目前还没看出 using 有什么巨大根本的优势,除了更现代化更干净些。
    对我有用[0] 丢个板砖[0] 引用 | 举报 | 管理
    #23 得分:0回复于: 2013-10-11 20:05:50
    引用 22 楼 ri_aje 的回复:
    也可以用 using,但和 traits 本质是一样的。
    反正我目前还没看出 using 有什么巨大根本的优势,除了更现代化更干净些。

    using与四楼的方法是不一样的(连本质也不一样),其实四楼那个方法还不能说是traits,它与traits只是形似,但神不似,traits的目的是非侵入式扩展,但四楼的方法显然与此沾不上边,它不过利用了一下一阶元函数的输出而已,就好像做一张椅子,缺个腿,当天的木头却用光了,于是临时用块砖头垫一下,这样也能凑合着用一天,但砖头始终是砖头,它永远不能代替椅子腿,只要用着砖头,这把椅子就是不完整的。

    模板别名就是这样一把椅子腿,四楼的方法就是这样一块砖头。无法typedef的模板本来就是语言设施设计时的疏漏,特别是template-id常常长得像鸡肠一样,模板的设计者竟然没想到给它个别名,C++11现在总算把这条椅子腿给补上来了。
    0 0