我尝试在函数参数上使用 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
是由第一个 参数推导出来的,而不是第二个。
关于c++ - 推导参数失败,适用于返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26638902/