【问题标题】:clang++ not accepting use of template template parameter when using CRTP使用 CRTP 时 clang++ 不接受使用模板模板参数
【发布时间】:2013-07-15 06:40:49
【问题描述】:

在使用带有 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++ templates c++11 clang crtp


    【解决方案1】:

    您的代码是合法的。

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

    与普通(非模板)类一样,类模板具有注入类名称(第 9 条)。 注入的类名可以用作模板名或类型名。 当它与模板参数列表一起使用时作为模板模板参数的模板参数,或作为详细类型说明符中的最终标识符在友元类模板声明中,它指的是类模板本身

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


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

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

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

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

    【讨论】:

    • +1 不知道这在 C++11 中发生了变化。您可能想提供我在现已删除的答案中的解决方法。
    • @DavidRodríguez-dribeas:不用担心,新标准仍然经常让我感到惊讶。
    • 我并不担心,相反我学到了一些东西。我会担心我没有学到任何新东西的那一天:)
    • 请注意,在 C++03 中需要 whitespace between &lt; and ::
    • @Jesse: 哇,C++11 对这种情况的最大咀嚼做了一个例外:“否则,如果接下来的三个字符是 &lt;:: 并且后面的字符既不是 : 也不是&gt;&lt; 本身被视为预处理器标记,而不是替代标记 &lt;: 的第一个字符“2.5p3
    猜你喜欢
    • 1970-01-01
    • 2016-04-16
    • 1970-01-01
    • 2013-11-17
    • 2019-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多