为啥 void_t 在 SFINAE 中不起作用但 enable_if 起作用

Posted

技术标签:

【中文标题】为啥 void_t 在 SFINAE 中不起作用但 enable_if 起作用【英文标题】:Why void_t doesnt work in SFINAE but enable_if does为什么 void_t 在 SFINAE 中不起作用但 enable_if 起作用 【发布时间】:2021-08-22 09:27:43 【问题描述】:

我试图了解 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>();

注释的代码有效,但第一个无效。编译器给了我错误,说有重新定义并且模板参数推导失败。有人可以解释为什么会这样吗?两个void_ts 应该是独立的吧?因为一行检查x,另一行检查y。我该如何解决?

【问题讨论】:

请注意,这适用于make_void trick。 【参考方案1】:

这似乎与CWG issue #1980 有关(感谢T.C. 纠正我)

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

template<typename... Ts> struct make_void  typedef void type;;
template<typename... Ts> using void_t = typename make_void<Ts...>::type;

(from cppreference)

live example on wandbox

【讨论】:

哇这个问题在 gcc 上新安装的 C++17 还没有解决? @VittorioRomeo 他们至少可以在库中使用 make_void 技巧.. std::void_t 指定为template &lt;class...&gt; using void_t = void; 这不是 1558。这与声明匹配有关,即两个 func 定义是否实际上声明了不同的函数模板或相同的函数模板。更接近 2037 年。 "所有提示似乎都指向 1558"?不是我。首先,您不会得到“模棱两可的过载”之类的东西,这表明 SFINAE 没有介入;相反,您会得到“重新定义”。其次,如果你删除了两个funcs 之一,那么剩下的一个会被适当地调用——或者产生一个错误。这也与 SFINAE 问题不一致。最后,只要有func 的两个定义,没有任何调用,就足以触发错误。再一次,这与 SFINAE 问题不一致。

以上是关于为啥 void_t 在 SFINAE 中不起作用但 enable_if 起作用的主要内容,如果未能解决你的问题,请参考以下文章

为啥jquery plusslider在google chrome中不起作用但在firefox中起作用

为啥切换屏幕在 kivy 中不起作用?

为啥“deleteBlocks”在 phpWord 中不起作用?

为啥以下操作在 Matlab 中不起作用

为啥拖放在 Selenium Webdriver 中不起作用?

为啥 View.Gone 在 Snackbar 中不起作用?