clang ++在使用CRTP时不接受使用模板模板参数

goj*_*oji 19 c++ templates clang crtp c++11

当在CRTP中使用模板模板参数时,尝试在派生初始化列表中调用基类构造函数时,我遇到编译错误.

可以使用以下代码片段复制问题:

template <template<class> class Derived, class T>
struct base
{
};

template <class T>
struct derived : public base<derived, T>
{
    derived()
        : base<derived, T>()
    { }
};
Run Code Online (Sandbox Code Playgroud)

违规错误消息:

bug.cpp:10:16: error: template argument for template template parameter must be a class template or type alias template
        : base<derived, T>()
               ^
bug.cpp:10:11: error: expected class member or base class name
        : base<derived, T>()
          ^
bug.cpp:10:11: error: expected '{' or ','
3 errors generated.
Run Code Online (Sandbox Code Playgroud)

这个问题似乎只出现在clang(3.4)上,而不是g ++(4.8,4.7,4.6).我正在使用-std = c ++ 11进行编译.

这是我第一次使用CRTP和模板模板参数.我这样做是否正确,这是clang ++的问题吗?

我已经开始相信clang ++错误消息比g ++更晚了!

Ben*_*igt 17

您的代码是合法的.

从C++ 11标准,第14.6.1节:

与普通(非模板)类一样,类模板具有注入类名(第9节).inject-class-name可以用作模板名称或类型名称.当它与template-argument-list一起使用时,作为模板模板参数的模板参数,或者作为友元类模板声明的详细类型指定器中的最终标识符,它指的是类模板本身.

看起来您的版本clang仍在实施旧规则.根据您的附加注释,它可能只在ctor-initializer-list中这样做.


用户DavidRodríguez - dribeas为尚未完全实现C++ 11注入类名称规则的编译器提供了一种解决方法.使用不合格的类的任何名称,例如:

derived()
    : base< ::derived, T >()
//          ^^ qualified with global namespace
{ }
Run Code Online (Sandbox Code Playgroud)

有些编译器也可能在继承列表中要求:

template <class T>
struct derived : public base< ::derived, T >
//                            ^^
Run Code Online (Sandbox Code Playgroud)

  • 请注意,在C++ 03中需要[在`<`和`::`]之间的空格(http://coliru.stacked-crooked.com/view?id=bc0dcc3299d98f5d4d5ee6a95933c7ac-0e5891ff8107f561b22ca21b6b60d875). (3认同)