C++ 为什么无效在SFINAE中不起作用,但如果起作用,则启用

C++ 为什么无效在SFINAE中不起作用,但如果起作用,则启用,c++,c++17,sfinae,C++,C++17,Sfinae,我试图理解SFINAE是如何工作的,我正在试验这个代码 #include <type_traits> struct One { using x = int; }; struct Two { using y = int; }; template <typename T, std::void_t<typename T::x>* = nullptr> void func() {} template <typename T, std::voi

我试图理解SFINAE是如何工作的,我正在试验这个代码

#include <type_traits>

struct One { 
  using x = int; 
};
struct Two { 
  using y = int; 
};

template <typename T, std::void_t<typename T::x>* = nullptr>
void func() {}
template <typename T, std::void_t<typename T::y>* = nullptr>
void func() {}

/*template <typename T, std::enable_if_t<std::is_same_v<typename T::x, typename T::x>>* = nullptr>
void func() {}
template <typename T, std::enable_if_t<std::is_same_v<typename T::y, typename T::y>>* = nullptr>
void func() {} */



int main() {
  func<One>();
  func<Two>();
}
#包括
结构一{
使用x=int;
};
结构二{
使用y=int;
};
模板
void func(){}
模板
void func(){}
/*模板
void func(){}
模板
void func(){}*/
int main(){
func();
func();
}

注释后的代码有效,但第一个代码无效。编译器给我错误,说有一个重新定义,模板参数推断失败。有人能解释一下为什么会这样吗?两个
void\t
s应该是独立的,对吗?因为一行检查
x
,另一行检查
y
。如何修复?

这似乎与(纠正我的学分)有关

作为一种解决方法,您可以将
void\t
定义为:

template<typename... Ts> struct make_void { typedef void type;};
template<typename... Ts> using void_t = typename make_void<Ts...>::type;
模板结构make_void{typedef void type;};
模板使用void\u t=typename make\u void::type;


请注意,这适用于。在gcc上新安装的C++17中,这个问题尚未解决?@VittorioRomeo他们至少可以在库中使用make_void技巧。
std::void_t
指定为
模板使用void_t=void这不是1558。这与声明匹配有关,即两个
func
定义是实际声明不同的函数模板还是相同的函数模板。接近2037年,“所有的线索似乎都指向1558”?对我来说不是。首先,你不会得到任何像“模糊过载”这样的东西,这表明SFINAE没有介入;相反,你会得到“重新定义”。其次,如果删除两个
func
s中的一个,则会相应地调用剩余的一个,或者产生错误。这也不符合SFINAE的问题。最后,只要有
func
的两个定义,而不进行任何调用,就足以触发错误。再一次,这与SFINAE问题不一致。