我编写了一个使用大量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;
}
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)
这是英特尔和铿锵,还是用g ++中的错误?如果它是英特尔和铿锵的,你认为它将在未来的版本中得到解决吗?
答案 0 :(得分:7)
在类Derived
中,名称Derived
引用(实例化)类,而不是类模板。请尝试Base< ::Derived, Type>
(小心在&lt;和::)之间留一个空格。
答案 1 :(得分:6)
在 C ++模板完整指南(Amazon)的第9.2.3节中,讨论了注入的类名称。引用:
类模板也注入了类名。然而,他们是 比普通的注入类名更奇怪:它们可以跟着 模板参数(在这种情况下,它们是注入类模板 名称),但如果他们没有跟随模板参数 表示以其参数为参数的类(或者,对于a 部分专业化,其专业化论点)。这解释了 以下情况:
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
}
请注意非限定名称如何引用注入的名称而不是 如果没有后面的列表,则考虑模板的名称 模板参数。为了弥补,我们可以强制命名 使用文件范围限定符::找到的模板。这有效, 但是我们必须小心不要创建一个所谓的有向图标记 &lt;:,它被解释为左括号。虽然比较少见, 这样的错误导致了令人困惑的诊断。
因此,您的代码中发生的事情是Base<Derived, Type>
被解释为Base<Derived<Type>, Type>
,其格式不正确。因此,您需要使用范围限定符::
,并在<
之间留出空格以避免使用有向图。