I have a struct CRTPBase
serving as a base class for curiously recurring template pattern. Its only use is to expose the derived type:
template<typename Derived>
struct CRTPBase {
using asdf = Derived;
};
Now, I use the class as follows:
struct D : public CRTPBase<D> {
static_assert(std::is_same<asdf, D>::value, "");
};
So far, no problem. Now, instead of using a "normal" struct, I'd like to use a templated one:
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, "");
};
On VS2012, the above compiles fine, but clang needs me to mention that asdf
is a type:
template<int N>
struct DTmpl : public CRTPBase<DTmpl<N>> {
static_assert(std::is_same<typename CRTPBase<DTmpl<N>>::asdf, DTmpl>::value, "");
};
Now, I introduce another struct Intermediate
, whose sole purpose is to "wrap" a given base class:
template<typename Base>
struct Intermediate : public Base {};
My intuition was that saying Intermediate<CRTPBase<..>>
instead of CRTPBase<..>
shall (essentially) make no difference.
However, both Visual Studio and clang compile the following:
struct DIntrmd : public Intermediate<CRTPBase<DIntrmd>> {
static_assert(std::is_same<asdf, DIntrmd>::value, "");
};
And both Visual Studio and clang reject the following:
template<int N>
struct DTmplIntrmd : public Intermediate<CRTPBase<DTmplIntrmd<N>>> {
static_assert(std::is_same<asdf, DTmplIntrmd>::value, "");
};
Again, I have to explicitly state that asdf
is a type so that it compiles:
template<int N>
struct DTmplIntrmd : public Intermediate<CRTPBase<DTmplIntrmd<N>>> {
static_assert(std::is_same<typename Intermediate<CRTPBase<DTmplIntrmd<N>>>::asdf, DTmplIntrmd>::value, "");
};
So, here's my question: Which is the correct compiler behaviour regarding the situation described?