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

标签 c++ templates c++11 clang crtp

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

可以用这段代码复制问题:

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

template <class T>
struct derived : public base<derived, T>
{
    derived()
        : base<derived, T>()
    { }
};

有问题的错误消息:

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.

这个问题似乎只发生在 clang (3.4) 上,而不是 g++ (4.8, 4.7, 4.6)。我也在用 -std=c++11 编译。

这是我第一次需要使用带有模板模板参数的 CRTP。我这样做可以吗?是否是 clang++ 的问题?

我对 clang++ 错误消息的信任度超过了最近的 g++!

最佳答案

您的代码是合法的。

来自 C++11 标准,第 14.6.1 节:

Like normal (non-template) classes, class templates have an injected-class-name (Clause 9). The injected-class-name can be used as a template-name or a type-name. When it is used with a template-argument-list, as a template-argument for a template template-parameter, or as the final identifier in the elaborated-type- specifier of a friend class template declaration, it refers to the class template itself.

看起来您的 clang 版本仍在执行旧规则。根据您的其他评论,它可能仅在 ctor-initializer-list 中这样做。


用户 David Rodríguez - dribeas为尚未完全实现 C++11 注入(inject)类名规则的编译器提供了一种解决方法。使用任何非限定类的名称,例如:

derived()
    : base< ::derived, T >()
//          ^^ qualified with global namespace
{ }

一些编译器可能在继承列表中也需要这个:

template <class T>
struct derived : public base< ::derived, T >
//                            ^^

关于c++ - 使用 CRTP 时 clang++ 不接受使用模板模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17687459/

相关文章:

c++ - 我应该让我的功能尽可能通用吗?

C++ 模板类默认构造函数失败

C++ 模板继承。子类应该用固定类型替换基类中的类型

c++ - 模板别名和 sfinae

c++ - 检测对象是否为智能指针所有

c++ - 多态性:成员访问和getter给出不同的结果

c++ - “提示”使用未定义的结构 - winSock

c++ - 在每次循环迭代时一起添加可变数量的数组元素

c++ - 在编译时使用未知类型的对象类

这个嵌套循环的算法复杂度