如何在Visual C++中延迟静态数据成员的实例化?

Jus*_*tin 8 c++ compatibility visual-c++ template-meta-programming c++14

以下代码适用于GCC和Clang,但不适用于Visual C++:

#include <type_traits>

struct MyType {
    static constexpr std::size_t it = 10;
};

struct MyType2 {
};

template<typename T>
struct Type2 {
    static constexpr std::size_t it = T::it;
};

int main() {
    Type2<MyType> t1;
    Type2<MyType2> t2; // Visual C++ complains that MyType2::it doesn't exist
    (void) t1;
    (void) t2;
}
Run Code Online (Sandbox Code Playgroud)

根据标准第14.7.1节:

...除非静态数据成员本身以需要静态数据成员定义存在的方式使用,否则不会发生静态数据成员的初始化(以及任何相关的副作用)

所以这似乎是Visual C++中的一个错误; 它应该接受这个代码.

无论如何,我仍然希望能够使用Visual C++来做到这一点.在不改变访问成员变量的语法的情况下,允许Visual C++工作的最简单方法是什么?我还要求Type2<T>::it在不存在时T::it不存在,或者否则可能SFINAE不存在Type2<T>::it.


这会改变语法,所以我不想要它:

template<typename T>
struct Type2 {
    template<typename = void>
    static constexpr std::size_t it = T::it;
};

// Type2<MyType>::it<>
Run Code Online (Sandbox Code Playgroud)

这是很多工作,因为我的类将包含多个简单的constexpr变量:

template<typename T, typename = void>
struct Type2 {
};

template<typename T>
struct Type2<T, decltype((void) T::it)> {
    static constexpr std::size_t it = T::it;
};
Run Code Online (Sandbox Code Playgroud)

Rei*_*ica 2

您可以继承it(如果存在)而不是直接声明它:

template<typename T, typename = void>
struct ItHolder
{};

template<typename T>
struct ItHolder<T, decltype((void) T::it)> {
    static constexpr std::size_t it = T::it;
};


template<typename T>
struct Type2 : ItHolder<T> {
};
Run Code Online (Sandbox Code Playgroud)

换句话说,只需采用您已经建议的内容,并使用另一层间接方式将其组合起来即可。