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