Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initializing base class static const variable with derived class variable, via CRTP

Tags:

c++

templates

The following program compiles and runs in Cygwin GCC 4.8.2 but not in MSCV 2008 (or MSVC 2013 either)

#include <iostream>

template<typename T>
struct Base
{
    static const unsigned BAR = T::FOO;

    static void func()
    {
        std::cout << BAR << std::endl;
    }
};

template<typename T>
struct Derived : Base<Derived<T> >
{
    static const unsigned FOO = 42;
};

int main()
{   
    Derived<int>::func();
}

MSVC error

Test.cpp(6) : error C2039: 'FOO' : is not a member of 'Derived<T>'
        with
        [
            T=int
        ]
        Test.cpp(16) : see reference to class template instantiation 'Base<T>' being compiled
        with
        [
            T=Derived<int>
        ]
        Test.cpp(24) : see reference to class template instantiation 'Derived<T>' being compiled
        with
        [
            T=int
        ]
Test.cpp(6) : error C2065: 'FOO' : undeclared identifier
Test.cpp(6) : error C2057: expected constant expression

Is this program compliant or is this an MSCV issue? Also, is there a workaround?

like image 579
Olumide Avatar asked May 18 '26 15:05

Olumide


1 Answers

EDIT 2 : it is enough to reject initialization after Derived class declaration.

The only way I could have MSVC and Clang compile your program is :

  • reject Base::BAR initialization after Derived class declaration
  • use a concrete implementation of Derived to initialize BAR

Edit : I think it is normal because in your code the compiler has no mean when compiling Base to know that T::FOO will exist and will be a constant value.

Current source is :

#include <iostream>

template<typename T>
struct Base
{
    static const unsigned BAR;

    static void func()
    {
        std::cout << BAR << std::endl;
    }
};

template<typename T>
struct Derived : Base<Derived<T> >
{
    static const unsigned FOO = 42;
};

template<typename T>
const unsigned Base<T>::BAR = T::FOO;

int main()
{   
    Derived<int>::func();
}
like image 148
Serge Ballesta Avatar answered May 20 '26 03:05

Serge Ballesta