参数扣除失败,返回值有效

Deduction fails on parameter, works on return value

本文关键字:返回值 有效 失败 参数      更新时间:2023-10-16

我试图在函数参数上使用std::enable_if来触发SFINAE。编译失败,出现以下错误:

type_nonsense.cpp:20:5: error: no matching function for call to 'c'
    c(SOME::VALUE);
    ^
type_nonsense.cpp:13:6: note: candidate template ignored: couldn't infer
      template argument 'T'
void c(typename std::enable_if<std::is_enum<T>::value, T>::type t) {}
     ^
1 error generated.

std::enable_if移动到返回类型或伪模板参数可以很好地工作。为什么?


#include <type_traits>
// Works
template <typename T, typename dummy = typename std::enable_if<std::is_enum<T>::value, T>::type>
void a(T t) {}
// Works
template <typename T>
typename std::enable_if<std::is_enum<T>::value, void>::type b(T t) {}
// Fails to compile
template <typename T>
void c(typename std::enable_if<std::is_enum<T>::value, T>::type t) {}
enum class SOME { VALUE };
int main() {
    a(SOME::VALUE);
    b(SOME::VALUE);
    c(SOME::VALUE);
}
嵌套名称说明符中的依赖类型是用于模板参数推导的非推导上下文,因此不能用于确定T的类型。将std::enable_if放在返回类型或作为默认模板参数中是有效的,因为T的类型在这些上下文中没有推导出来。

如果你需要把它作为一个参数,你可以这样做:

template <typename T>
void c(T t, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr) {}

这是因为T是由第一个参数推导的,而不是第二个。

对于编译失败的,T不可扣除。