c++ - CRTP派生类貌似不知道继承类型

标签 c++ templates c++11 crtp

我有一个结构CRTPBase作为奇怪的重复模板模式的基类。它的唯一用途是公开派生类型:

template<typename Derived>
struct CRTPBase {
    using asdf = Derived;
};

现在,我按如下方式使用该类:

struct D : public CRTPBase<D> {
    static_assert(std::is_same<asdf, D>::value, "");
};

到目前为止,没有问题。现在,我不想使用“普通”结构,而是使用模板化结构:

template<int N>
struct DTmpl : public CRTPBase<DTmpl<N>> {
    // the following compiles under VS2012, but not in clang
    static_assert(std::is_same<asdf, DTmpl>::value, "");
};

在 VS2012 上,上面的代码编译得很好,但是 clang 需要我提到 asdf是一种类型:

template<int N>
struct DTmpl : public CRTPBase<DTmpl<N>> {
    static_assert(std::is_same<typename CRTPBase<DTmpl<N>>::asdf, DTmpl>::value, "");
};

现在,我介绍另一个结构体 Intermediate ,其唯一目的是“包装”给定的基类:

template<typename Base>
struct Intermediate : public Base {};

我的直觉是这样说的Intermediate<CRTPBase<..>>而不是CRTPBase<..> (本质上)没有什么区别。

但是,Visual Studio 和 clang 都会编译以下内容:

struct DIntrmd : public Intermediate<CRTPBase<DIntrmd>> {
    static_assert(std::is_same<asdf, DIntrmd>::value, "");
};

Visual Studio 和 clang 都拒绝以下内容:

template<int N>
struct DTmplIntrmd : public Intermediate<CRTPBase<DTmplIntrmd<N>>> {
    static_assert(std::is_same<asdf, DTmplIntrmd>::value, "");
};

我必须再次明确声明asdf是一种类型,因此可以编译:

template<int N>
struct DTmplIntrmd : public Intermediate<CRTPBase<DTmplIntrmd<N>>> {
    static_assert(std::is_same<typename Intermediate<CRTPBase<DTmplIntrmd<N>>>::asdf, DTmplIntrmd>::value, "");
};

所以,这是我的问题:对于所描述的情况,哪种编译器行为是正确的?

最佳答案

根据[temp.res]

A name used in a template declaration or definition and that is dependent on a template-parameter is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename.

所以在这个例子中:

template<int N>
struct DTmpl : public CRTPBase<DTmpl<N>> {
    // the following compiles under VS2012, but not in clang
    static_assert(std::is_same<asdf, DTmpl>::value, "");
};

asdf 是依赖于模板参数的名称,因此应假定不命名类型,因为它未由 typename 限定>。 VS2012编译这段代码是错误的,而clang是正确的。

在您问题中的每个其他示例中,asdf 要么不依赖(并且两个编译器都接受代码),要么依赖(并且两个编译器都拒绝它)。所有其他行为都是正确的。

有关更多信息,请参阅Where and why do I have to put the "template" and "typename" keywords? .

关于c++ - CRTP派生类貌似不知道继承类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31610809/

相关文章:

c++ - Boost::typeof 编译器问题:修改 typeof,使用 decltype 代替

c++ - 拉普拉斯算子没有给出所需的输出

c++ - 如何将字符串迭代器变量传递给C++中的函数?

c++ - 在 wxwidgets 中,如何锁定在 gui 线程和工作线程之间共享的 vector ?

c++ - unique_ptr 设置

c++ - C++11 是否重新初始化已初始化的成员字段?

C++11,枚举类,g++ 的 undefined reference ,与 clang++ 一起工作

c++ - WM_ENDSESSION 消息有问题

c++ - 类模板,允许用户定义类型 C++

templates - Angular 2 Dart 模板语法 : How to access static methods?