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;
}

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)

intel と clang、または g++ のバグですか? intel と clang にある場合、将来のバージョンで解決されると思いますか?

4

2 に答える 2

7

class 内Derivedでは、名前Derivedはクラス テンプレートではなく (インスタンス化された) クラスを参照します。代わりに試してくださいBase< ::Derived, Type>(< と :: の間にスペースを入れるように注意してください)。

于 2013-01-08T14:42:57.613 に答える
6

C++ Template the Complete Guide ( Amazon ) のセクション 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
}

修飾されていない名前が挿入された名前をどのように参照しているかに注意してください。その後にテンプレート引数のリストが続かない場合、テンプレートの名前とは見なされません。これを補うために、ファイル スコープ修飾子 ::. これは機能しますが、いわゆる有向グラフ トークン <: を作成しないように注意する必要があります。これは左ブラケットとして解釈されます。比較的まれですが、このようなエラーは複雑な診断をもたらします。

したがって、コードで何が起こるかは、それが形式が正しくないBase<Derived, Type>と解釈されBase<Derived<Type>, Type>ていることです。したがって、有向グラフを避けるために、::間にスペースを入れてスコープ修飾子を使用する必要があります。<

于 2013-01-08T16:03:35.787 に答える