Clang和Intel无法编译此CRTP代码

Vin*_*ent 11 c++ templates compiler-errors crtp c++11

我编写了一个小型库,它使用了大量的C++ 11元编程技术和CRTP,它与g ++ 4.7.2编译得很好.

现在,我尝试使用Intel icpc 13.0.0.079进行编译,它会产生数百个错误.所以我试着一个接一个地隔离问题.

所以,首先,考虑一下在g ++ 4.7.2下编译没有问题的代码

#include <iostream>

template<template<typename> class Crtp, typename Type>
struct Base {};

template<typename Type>
struct Derived : public Base<Derived, Type>
{
    Derived(): Base<Derived, Type>() {;}
};

int main()
{
    Derived<int> x;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

icpc和clang都无法编译此代码:

test_crtp.cpp(26): error: type "Derived<Type>::Derived" is not a class template
      Derived(): Base<Derived, Type>() {;}
                      ^

test_crtp.cpp(26): error: "Base" is not a nonstatic data member or base class of class "Derived<int>"
      Derived(): Base<Derived, Type>() {;}
                 ^
          detected during instantiation of "Derived<Type>::Derived() [with Type=int]" at line 31

compilation aborted for test_crtp.cpp (code 2)
Run Code Online (Sandbox Code Playgroud)

那么它是英特尔和铿锵,还是用g ++中的错误?如果它是英特尔和铿锵的,你认为它将在未来的版本中得到解决吗?

Mar*_*sse 7

在类中Derived,名称Derived是指(实例化的)类,而不是类模板.请尝试Base< ::Derived, Type>(小心在<和::)之间留一个空格.

  • 在C++ 11,你可以只写`<:: Derived`的`<:`不解释为模板参数列表中有向图. (5认同)
  • 注意:对于空间的原因是,`<:`可以被解释为一个[有向图(http://en.wikipedia.org/wiki/Digraphs_and_trigraphs),因此`<::`将被视为`[ :`经过预处理...... (4认同)

Tem*_*Rex 6

C++模板完整指南(亚马逊)的9.2.3节中,讨论了注入类名称.报价:

类模板也有注入的类名.但是,它们比普通的注入类名更奇怪:它们可以跟随模板参数(在这种情况下它们是注入类模板名称),但是如果它们后面没有模板参数,则它们表示以其参数作为参数的类(或者,对于部分专业化,其专业化论点).这解释了以下情况:

template<template<typename> class TT> 
class X {};

template<typename T> 
class C 
{
    Ca;        // OK: same as ''C<T> a;''
    C<void> b; // OK
    X<C> c;    // ERROR: C without a template argument list
               // does not denote a template
    X<::C> d;  // ERROR: <: is an alternative token for [
    X< ::C> e; // OK: the space between < and :: is required
}
Run Code Online (Sandbox Code Playgroud)

请注意非限定名称如何引用注入名称,如果模板名称后面没有模板参数列表,则不会将其视为模板名称.为了补偿,我们可以使用文件范围限定符::强制找到模板的名称.这是有效的,但我们必须小心不要创建一个所谓的有向图标记<:,它被解释为左括号.虽然相对罕见,但这种错误会导致令人困惑的诊断.

那么代码中发生的事情Base<Derived, Type>就是被解释为Base<Derived<Type>, Type>格式错误.因此,您需要使用范围限定符::之间的空格<来避免有向图.