prestokeys
prestokeys

Reputation: 4839

CRTP compiling error

The following will compile with GCC 5.2 but not with Visual Studio 2015.

template <typename Derived>
struct CRTP {
    static constexpr int num = Derived::value + 1;
};

struct A : CRTP<A> {
    static constexpr int value = 5;
};

It complains that A does not have a member named value. How to fix the code so that it compiles on both compilers? Or is it illegal altogether?

Upvotes: 4

Views: 382

Answers (2)

Barry
Barry

Reputation: 303947

The problem is here:

template <typename Derived>
struct CRTP {
    static constexpr int num = Derived::value + 1;
                               ↑↑↑↑↑↑↑↑↑
};

At the time of the instantiation of CRTP<A>, A isn't a complete class yet, so you can't actually access static members of it.

One workaround is to pass in num as a separate template argument:

template <typename Derived, int N>
struct CRTP {
    static constexpr int num = N;
};

struct A : CRTP<A, 5> {

};

Upvotes: 4

Try making it a constexpr function instead. The way you have it setup now attempts to access an incomplete type.
Since a templated member function will only be initialized upon first being used, type A will be fully defined by that point.

#include <iostream>

template <typename Derived>
struct CRTP {
    static constexpr int num() { return  Derived::value + 1; }
};

struct A : CRTP<A> {
    static constexpr int value = 5;
};

int main()
{
    std::cout << A::num();
    return 0;
}

See it live here

Upvotes: 5

Related Questions