[转]gcc中使用模板类的类的编译错误

原文:http://blog.csdn.net/manesking/archive/2008/10/29/3173632.aspx

撰写时间:2008年03月12日
发布时间:2008年10月29日
整理时间:2008年10月29日

    最近在自己写的一段代码中,使用了模板类的类,即如下形式:
    template<class A>
    void func(A)
    {
        fun2(A::B());
    }
    即A是一个模板类型,同时使用了A域下的类型B,需要根据A的不同而构造相应的B的实体,进行传递。
    此种写法在VC6 + IntelC++9.0环境中能够通过编译,且程序行为与我想要的一致,(后来认为,估计Intel的编译器比较智能,或过于智能)。 
    但在cygwin + gcc3.4.4中却不能通过编译,其错误信息为:
    instantiated from here
    error: dependent-name `A::B' is parsed as a non-type, but instantiation yields a type
    note: say `typename A::B' if a type is meant

    其大致意思为:“编译器解析A::B不是个类型,但却要被初始化为一个类型。”
    但是A::B确实是一个类型,这是基于我们通常使用类或名字空间下的子类的惯用语法,考虑可能是gcc对模板类的这种情况考虑不周,因而没能解析出这种用法。
    随后又将该错误信息在百度里搜了一下,结果得到了正确的答案:
    原来标准c++要求显示地声明一个类型是模板类型,诸如此类的如list<T>::iterater(当T是模板类型时), 包括vector,map都会有这样的问题,理由是具体类型的空间域名也是个“不确定”类型,所以要求有显示地typename声明,指示它是个模板类型 或名字。
    
    其实gcc足够“聪明”,在错误信息里它已经提示你(最后一句话):“使用typename关键字声明,如果它是一个类型的含义”。只是我当时没有仔细看懂,呵呵。
    如此修改即可:
    template<class A>
    void func(A)
    {
        fun2(typename A::B()); //在前面加typename即可,这里不接受”class”
    }

    

    此外,从这一点上,可以看到typename关键字在模板编程中有其独特的用法,而并不是与最初的理解那样,是个可以与class混用,可有可无的东西,建议将template<class A>语法中的class都替换为typename,可能会更规范些。

posted @ 2009-02-27 13:53  musée  阅读(2248)  评论(0编辑  收藏  举报