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