【问题标题】:CRTP derived class seemingly does not know inherited typeCRTP派生类貌似不知道继承类型
【发布时间】:2015-07-24 12:41:14
【问题描述】:

我有一个结构 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&lt;CRTPBase&lt;..&gt;&gt; 而不是 CRTPBase&lt;..&gt; 应该(基本上)没有区别。

然而,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, "");
};

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

【问题讨论】:

  • 在您的第一个示例中,您可以使用typename DTmpl::asdf 而不是typename CRTPBase&lt;DTmpl&lt;N&gt;&gt;::asdf。即只是懒惰并使用派生类(您当前正在定义的)而不是基类。

标签: c++ templates c++11 crtp


【解决方案1】:

根据 [temp.res]

在模板声明或定义中使用并且依赖于 模板参数 的名称是 假定不命名类型,除非适用的名称查找找到类型名称或名称是合格的 通过关键字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?

【讨论】:

  • 对于templatetypename 问题,我倾向于直接回答问题并链接到您链接的问题,因为即使使用该链接,人们有时也不明白如何应用它针对他们的特定问题。
猜你喜欢
  • 2023-03-20
  • 2015-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-04
  • 1970-01-01
  • 2021-10-25
相关资源
最近更新 更多