为什么void_t在SFINAE中不起作用,但enable_if起作用

18 c++ sfinae c++17

我试图了解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>();
}
Run Code Online (Sandbox Code Playgroud)

注释代码有效,但第一个没有.编译器给出了错误,指出存在重新定义且模板参数推断失败.有人能解释为什么会这样吗?这两个void_t应该是独立的吗?由于一行检查x而另一行检查y.我该怎么办?

Vit*_*meo 14

这似乎与CWG问题#1980 (TC为纠正我的信用)有关.

作为一种解决方法,您可以定义void_t为:

template<typename... Ts> struct make_void { typedef void type;};
template<typename... Ts> using void_t = typename make_void<Ts...>::type;
Run Code Online (Sandbox Code Playgroud)

(来自cppreference)

wandbox上的实例

  • "所有提示似乎都指向1558"?不是我 首先,你没有得到任何类似"模糊过载"的东西,这表明SFINAE没有踢; 相反,你得到"重新定义".其次,如果你删除两个`func`s中的一个,那么剩下的一个被调用 - 或者产生错误 - 适当.这也与SFINAE问题不一致.最后,只有`func`的两个定义,没有任何调用,足以触发错误.再一次,这与SFINAE问题不一致. (5认同)
  • 实际上,CWG 1980就是问题. (4认同)
  • 使用void_t = void;`将`std :: void_t`指定为`template <class ...> (2认同)
  • 这不是1558.这与声明匹配有关,即两个`func`定义是否实际声明了不同的函数模板或相同的函数模板.接近2037年. (2认同)