以下代码适用于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节:
......静态的初始化(以及任何相关的副作用) 除非静态数据成员本身,否则不会发生数据成员 以需要定义静态数据成员的方式使用 存在
所以这似乎是Visual C ++中的一个错误;它应该接受这个代码。
无论如何,我仍然希望能够使用Visual C ++来做到这一点。在不改变访问成员变量的语法的情况下,允许Visual C ++工作的最简单方法是什么?我还要求Type2<T>::it
在T::it
不存在时不存在,或者除Type2<T>::it
之外可能存在SFINAE。
这改变了语法,所以我不想要它:
template<typename T>
struct Type2 {
template<typename = void>
static constexpr std::size_t it = T::it;
};
// Type2<MyType>::it<>
这是很多工作,因为我的课程将包含一个简单的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;
};
答案 0 :(得分: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> {
};
换句话说,只需采用您已建议的内容并使用另一层间接方法将其组合。