vendredi 24 juillet 2015

CRTP derived class seemingly does not know inherited type

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?

Aucun commentaire:

Enregistrer un commentaire