简体   繁体   English

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

[英]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.

相关问题 如何解决与GCC / Clang(无法识别的模板定义)不同的C ++函数模板的MSVC处理? - How to solve MSVC treatment of C++ function templates that is different than that of GCC/Clang (unrecognizable template definition)? C++ 使用 GCC 使用 cmake 编译简单测试,使用 clang 时 GTest 失败 - C++ Compiling simple test with cmake using GCC and GTest fails while using clang works 使用enable_if的模板特化在Clang中失败,适用于GCC - Template specialization with enable_if fails in Clang, works with GCC 离线构造函数模板在GCC中无法在Clang中运行 - out-of-line constructor template works in GCC fails in Clang 可变参数模板适用于 gcc 但不适用于 clang - Variadic template works in gcc but not in clang 具有结构成员的 C++ 联合结构适用于 Clang 和 MSVC,但不适用于 GCC - C++ union struct with struct member works on Clang and MSVC but not GCC C++:MSC 未解析模板运算符(gcc 和 clang 正常) - C++: MSC not resolving a template operator (gcc and clang ok) gcc因模板递归而失败,而clang则没有 - gcc fails with template recursion, while clang does not C++20 概念:在 MSVC 中,行外定义失败,但在 GCC 或 clang 中失败 - C++20 Concepts: out-of-line-definition fails with MSVC but not in GCC or clang 忽略Clang候选模板:替换失败(也无法使用gcc编译,VC工作正常) - Clang candidate template ignored: substitution failure (also fails to compile with gcc, VC works fine)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM