通过CRTP使用派生类变量初始化基类静态const变量

时间:2014-12-12 11:49:32

标签: c++ templates

以下程序在Cygwin GCC 4.8.2中编译并运行,但不在MSCV 2008(或MSVC 2013)中编译和运行

#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错误

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

此程序是否合规或是MSCV问题?还有,有解决方法吗?

2 个答案:

答案 0 :(得分:1)

编辑2:在Derived类声明之后拒绝初始化就足够了。

我可以让MSVC和Clang编译你的程序的唯一方法是:

  • 在派生类声明后拒绝Base :: BAR初始化
  • 使用Derived的具体实现来初始化BAR

编辑:我认为这是正常的,因为在你的代码中,编译器在编译Base 时没有意思知道T :: FOO将存在并且将是一个常量值。

目前的来源是:

#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();
}

答案 1 :(得分:0)

你可以通过不从Base派生Derive来打破Base和Derive之间的依赖关系循环(在你不需要这样做的例子中)

顺便说一下,clang也无法编译你的例子并给出与vstudio相同的错误

#include <iostream>


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

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

struct Derived
{
    static const unsigned FOO = 42;
};

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