clang上的C ++模板定义失败,适用于GCC

时间:2014-05-20 08:13:44

标签: c++ templates gcc clang

以下代码在GCC上编译(甚至不需要最新版本),但在第3.4段失败:

template <int N>
struct T_unsigned {
    typedef typename T_unsigned<N>::Type Type;
};

template <> struct T_unsigned<8> {
    typedef unsigned char Type;
};

使用上面的T_unsigned定义,GCC允许你使用&#34; T_unsigned&lt; 8&gt; :: Type&#34;而不是&#34; unsigned char&#34;。当我尝试使用clang 3.4编译它时,我得到:

test.cpp:3:41: error: no type named 'Type' in 'T_unsigned<N>'
    typedef typename T_unsigned<N>::Type Type;
            ~~~~~~~~~~~~~~~~~~~~~~~~^~~~
1 error generated.

clang是否无法编译正确的C ++ 11代码,或者此代码是否采取了非GCC恰好支持的标准?

2 个答案:

答案 0 :(得分:0)

在您的一般情况T_unsigned<N>中,我们有:

  

如果名称是

,则该名称是当前实例化的成员      

[...]

     
      
  • 一个qualified-id,其中嵌套名称说明符引用当前实例化。

    [ Example:
      template <class T> class A {
         static const int i = 5;
         int n1[i]; // i refers to a member of the current instantiation
         int n2[A::i]; // A::i refers to a member of the current instantiation
         int n3[A<T>::i]; // A<T>::i refers to a member of the current instantiation
         int f();
      };
    
  •   

T_unsigned<N>中,T_unsigned<N>只是其自身的另一个名称。所以基本上你有类似的东西:

class Foo {
    typedef Foo::Type Type;
};

并且“正确”错误消息应大约为(http://ideone.com/FvJHBF):

     prog.cpp:2:17: error: ‘Type’ in ‘class Foo’ does not name a type
     typedef Foo::Type Type;
             ^

但是,您写道,您在使用专业化T_unsigned<8>时遇到问题,而这似乎是clang找不到的。

您的测试用例并非详尽无遗,所以我的回答取决于if语句:

如果在实例化时,您对N=8的专业化是可见的,那么铿锵是错误的。如果没有,gcc和clang都应该失败,但是有上述错误消息(尽管标准没有定义错误消息本身,所以这是一个工具的应该,而不是标准的)。 / p>

答案 1 :(得分:0)

您用作typedef的名称不依赖(请参阅定义从属名称的子句),并且该位置的定义上下文中的namelookup将找不到声明。这本身就是一个错误。

但由于该名称尚未声明,因此该名称也不是当前实例化或其基类的类的成员。因此,该名称不是当前实例化的成员,因此我们有另一个理由通过规则拒绝它,如果限定符是当前实例化,则该名称必须引用该实例化的成员或成员一个未知的专业化(如果该类具有依赖的基类,则会出现这种情况)。

注意&#34;当前实例化的概念&#34;:限定符的含义是固定的,用于引用实例化周围模板的结果,我们不等待解析模板参数。因此,该术语不被称为“#34;当前专业化”,因为我们知道它指的是实例化的特化,而不是后来声明的显式特化。

我认为C ++ 03的情况有所不同。该名称将是依赖的,并且模板定义更难以被认为是可用的规则。但是,当您尝试在提供显式特化之前实例化模板时,会发生格式错误,无需诊断的行为。我认为这样的代码引用本身是没有意义的,因为你永远无法有效地实例化模板(并且有一条规则允许在这种情况下立即拒绝模板)。