C++ SFINAE:检测成员变量的存在对g++;

C++ SFINAE:检测成员变量的存在对g++;,c++,g++,sfinae,C++,G++,Sfinae,我试图将中用于检测类是否具有成员变量x的方法与结合起来,根据使用enable\u if的方法选择不同的实现 基本上,我想编写一个trait类,在给定类型T的情况下,该类提供对成员T::x的访问(如果存在),否则提供默认值 以下代码未在g++上编译:() #包括 #包括 //具有/不具有x成员的类 具有x{static constexpr int x=42;}的结构; 不带x{}的结构; //检测x的特征 模板 结构HasX:std::false_type{}; 模板 结构HasX:std::tr

我试图将中用于检测类是否具有成员变量
x
的方法与结合起来,根据使用
enable\u if
的方法选择不同的实现

基本上,我想编写一个trait类,在给定类型
T
的情况下,该类提供对成员
T::x
的访问(如果存在),否则提供默认值

以下代码未在g++上编译:()

#包括
#包括
//具有/不具有x成员的类
具有x{static constexpr int x=42;}的结构;
不带x{}的结构;
//检测x的特征
模板
结构HasX:std::false_type{};
模板
结构HasX:std::true_type{};
//trait为x提供默认值
模板
结构脚印
{
模板
静态constexpr std::enable_if_tx(){return t::x;}
模板
静态constexpr std::enable_if_t x(){return 1;}
};
int main(){

std::coutSFINAE只能在即时上下文中工作。换句话说,如果编译器可以提前看到声明有问题,那么它一定是错误

当实例化一个类时,编译器将尝试解析它所能解析的所有内容。如下所示:

template<bool enable = HasX<T>::value>
....

理论上,
U
可能是一种完全不同的类型。
U
直接用于函数实例化,而
T
则不是。

事实上:

//std::cout << HasX<WithoutX>::value << std::endl;

这确实解决了问题。

您可以使用:
std::void\u t
这个建议有效,谢谢。那么哪个编译器是错的,g++还是clang/msvc?问题不在
FooTraits
中,而在这两个编译器中都使用
void\u t
进行修复。有趣的是,这个变体适用于gcc 5+,但失败了(带注释行和不带注释行)4.9.4,根据注释行编译。该问题似乎与CWG1558有关。此处解释的
void\u t
的更复杂定义也适用于该gcc。
template <typename U = T, bool enable = HasX<U>::value>
static constexpr std::enable_if_t< enable, size_t> x() { return T::x; }
template <typename U = T, bool enable = HasX<U>::value>
static constexpr std::enable_if_t<!enable, size_t> x() { return 1; }
//std::cout << HasX<WithoutX>::value << std::endl;
template <typename T>
struct HasX <T, decltype((void) T::x)> : std::true_type {};
template <typename T>
struct HasX <T, std::void_t<decltype(T::x)>> : std::true_type {};