[英]C++ template definition fails on clang, works on GCC
The following code compiles on GCC (doesn't even require a recent version), but it fails on clang 3.4: 以下代码在GCC上编译(甚至不需要最新版本),但在clang 3.4上失败:
template <int N>
struct T_unsigned {
typedef typename T_unsigned<N>::Type Type;
};
template <> struct T_unsigned<8> {
typedef unsigned char Type;
};
Using the above definition of T_unsigned, GCC allows you to use "T_unsigned<8>::Type" instead of "unsigned char". 使用上面的T_unsigned定义,GCC允许您使用“T_unsigned <8> :: Type”而不是“unsigned char”。 When I try to compile this using clang 3.4, I get: 当我尝试使用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.
Is clang failing to compile correct C++11 code, or is this code doing something non-standard that GCC happens to support? clang是否无法编译正确的C ++ 11代码,或者此代码是否采取GCC恰好支持的非标准代码?
In your general case T_unsigned<N>
, we have: 在一般情况下, T_unsigned<N>
,我们有:
A name is a member of the current instantiation if it is 名称是当前实例化的成员(如果是)
[...] [...]
A qualified-id in which the nested-name-specifier refers to the current instantiation. 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(); };
Within T_unsigned<N>
, T_unsigned<N>
is just another name for itself. 在 T_unsigned<N>
, T_unsigned<N>
只是它自己的另一个名称。 So basically you have something like: 所以基本上你有类似的东西:
class Foo {
typedef Foo::Type Type;
};
and the "correct" error message should be approximately ( http://ideone.com/FvJHBF ): 并且“正确”错误消息应大约是( http://ideone.com/FvJHBF ):
prog.cpp:2:17: error: ‘Type’ in ‘class Foo’ does not name a type
typedef Foo::Type Type;
^
However, you write that you have problems with using your specialization T_unsigned<8>
, which is seemingly not found by clang. 但是,你写道你在使用专门化T_unsigned<8>
遇到了问题,而这似乎是clang找不到的。
Your testcase is not too exhaustive, so my answer depends on an if-statement: 你的测试用例并不详尽,所以我的答案取决于if语句:
If at the point of instantiation, your specialization for N=8
is visible, than clang is doubly wrong. 如果在实例化时,你对N=8
专业化是可见的,那么铿锵是双重错误的。 If not, gcc and clang should both fail, but with aforementioned error message (though the error message itself is in no way defined by the standard, so this is a tool's should , not a standard's). 如果没有,gcc和clang都应该失败,但是有上述错误消息(虽然错误消息本身没有被标准定义,所以这是一个工具应该 ,而不是标准的)。
The name that you use as the typedef is not dependent (see the clauses that define dependent names) and the namelookup in definition context at that place will not find a declaration. 您用作typedef的名称不依赖(请参阅定义依赖名称的子句),并且该位置的定义上下文中的namelookup将找不到声明。 That in itself is an error already. 这本身就是一个错误。
But since there is no declaration for the name yet, the name is also not a member of a class that is the current instantiation or a base class thereof. 但由于该名称尚未声明,因此该名称也不是当前实例化或其基类的类的成员。 Therefore the name is not a member of the current instantiation and therefore we have another reason to reject it by a rule that says that if the qualifier is the current instantiation, the name either must refer to a member of that instantiation, or to a member of an unknown specialization (which would be the case if the class had dependent base classes). 因此,该名称不是当前实例化的成员,因此我们有另一个理由通过规则拒绝它,如果限定符是当前实例化,则该名称必须引用该实例化的成员或成员一个未知的专业化(如果该类具有依赖的基类,则会出现这种情况)。
Note the notion of "current instantiation": the meaning of the qualifier is fixed to refer to the result of instantiating the surrounding template, we don't wait for resolving the template arguments. 注意“当前实例化”的概念:限定符的含义是固定的,用于引用实例化周围模板的结果,我们不等待解析模板参数。 Hence the term is not called "current specialization", since we know that it refers to an instantiated specialization, as opposed to a later declared explicit specialization. 因此,该术语不称为“当前专业化”,因为我们知道它指的是实例化的特化,而不是后来声明的显式特化。
The thing is different for C++03 I think. 我认为C ++ 03的情况有所不同。 The name will be dependent and the template definition is harder to deem illformed with the rules available. 该名称将是依赖的,并且模板定义更难以被认为是可用的规则。 The illformed, no diagnostic required, behavior will however happen when you try to instantiate the template before providing the explicit specialization. 但是,当您尝试在提供显式特化之前实例化模板时,会发生格式错误,无需诊断的行为。 I think such code refering to itself makes no sense because you never are able to actually instantiate the template validly (and there is a rule that allows rejecting a template straight away in such cases). 我认为这样的代码引用本身是没有意义的,因为你永远无法实际有效地实例化模板(并且有一条规则允许在这种情况下立即拒绝模板)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.