Search code examples
c++c++17ctad

Template rules in CRTP with MSVC


Consider the following code:

template <class Derived>
class KFBase
{
public:
    template <typename Nom>
    struct State {
        Nom nominal_state;
    };
    
};

template <typename A>
class PFilter
    : public KFBase<PFilter<A>>
{
public:
    using Base = KFBase<PFilter<A>>;
    // comment this out and it works
    using State = typename Base::State<int>;
};



int main(int, char**){
    PFilter<int>{};
}

As hinted in the comment, if I comment out the State alias everything compiles fine on MSVC. However, if I include it, I get a compile error when compiling with C++17 or C++20 (https://godbolt.org/z/aM78ToMsc), but rolling back to C++14 it works again on MSVC (https://godbolt.org/z/Eej9bjrf7)

On GCC this compiles just fine with C++20, so I'm wondering if I'm following the C++ standard or this is a bug introduced in the C++17 MSVC implementation.

My gut feeling is that this has something to do with CTAD, but I'm not sure.

Anyone can elucidate here?

P.S. If anyone has a better title for this question, please let me know.


Solution

  • You might need a template to indicate that < is not a comparison

    using State = typename Base::template State<int>;
    

    MSVC is pretty lax in C++14 mode (because at the time it was). Later versions have a /permissive- flag turned on by default.

    In later standards you can instead remove the typename, because using is now known to always require a type following the =. This is complicated. :-)

    Perhaps gcc also has a more permissive mode by default, I don't know.