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

标签 c++ visual-c++ c++14 compatibility template-meta-programming

以下代码适用于 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;
}

根据标准第 14.7.1 节:

... the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist

看来这是 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<>

这是很多工作,因为我的类(class)将包含的不仅仅是一个简单的 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;
};

最佳答案

您可以继承(当它存在时)而不是直接声明它:

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> {
};

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

关于c++ - 如何在 Visual C++ 中延迟静态数据成员的实例化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44174489/

相关文章:

c++ - 调试编译的可执行文件 : Why not abort gracefully on invalid write to NULL?

winapi - MFTransform 编码器->ProcessInput 返回 E_FAIL

c++ - constexpr 环境中 std::array 上的 std::prev

c++ - 带有大括号初始化的 make_unique

c++ - unique_ptr 的 move 语义

c++ - 使用#iostream 设置小数点

c++ - 使用 placement new 更新引用成员?

c++ - fmt 库 - 格式化为(编译时)string_view

windows - 加载 PE 文件的资源时

c++ - 检查枚举类是否包含特定标识符