【发布时间】: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<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, "");
};
所以,这是我的问题:对于所描述的情况,正确的编译器行为是什么?
【问题讨论】:
-
在您的第一个示例中,您可以使用
typename DTmpl::asdf而不是typename CRTPBase<DTmpl<N>>::asdf。即只是懒惰并使用派生类(您当前正在定义的)而不是基类。