我尝试在函数参数上使用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);
}
答案 0 :(得分:5)
嵌套名称说明符中的依赖类型是模板参数推导的非推导上下文,因此不能用于确定T
的类型。将std::enable_if
放在返回类型或默认模板参数中是有效的,因为T
的类型不会在这些上下文中推断出来。
如果您需要将其作为参数放置,您可以这样做:
template <typename T>
void c(T t, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr) {}
这是有效的,因为T
是由第一个参数推断的,而不是第二个。{/ p>
答案 1 :(得分:1)
对于无法编译的人,T
不可扣除。