`typename = enable_if_t<...>` 和 `enable_if_t<...,bool> = true` 的区别

Difference between `typename = enable_if_t<...>` and `enable_if_t<...,bool> = true`

在 SFINAE 中使用 typename = enable_if_t<...>enable_if_t<...,bool> = true 有什么区别吗?我特意询问,因为我偶然发现了一个看起来像错误的东西:Compiler error with a fold expression in enable_if_t

所以我很好奇两者之间是否有任何实际差异

是的,有区别。第一个不起作用,而第二个起作用。原因是默认模板参数不是函数签名的一部分。

"work" 我的意思是第一个版本不会从候选重载集中删除函数,这通常是使用 enable_if 时的预期目标。

可以在此处找到示例(@NathanOliver 提供): http://coliru.stacked-crooked.com/a/a15a6f1d0eaff4ab

存在细微差别,但都可用于 SFINAE。

typename = enable_if_t<...> 表单不允许 "simple" 重载:

template <typename T, typename = enable_if_t<cond<T>::value>>
void foo();

template <typename T, typename = enable_if_t<!cond<T>::value>>
void foo(); // Error: redeclaration of same function as default are not part of signature
            // Both are just template <typename, typename> void foo()

enable_if_t<cond, bool> = true 不受此影响:

template <typename T, enable_if_t<cond<T>::value, bool> = true>
void foo();

template <typename T, enable_if_t<!cond<T>::value, bool> = true>
void foo();

typename = enable_if_t<...> 的另一个问题是使用可能被劫持:

template <typename T, typename = enable_if_t<cond<T>::value>>
void foo();

template <typename T, typename = enable_if_t<cond<T>::value>>
void bar(T);


foo<int>();   // Regular usage, SFINAE occurs
bar(42);      // Regular usage, SFINAE occurs
bar<int>(42); // Possible usage, SFINAE still occurs
// But
foo<int, void>();   // No substitution fails here, so no SFINAE
bar<int, void>(42); // No substitution fails here, so no SFINAE