参数的扣除失败,对返回值起作用

时间:2014-10-29 19:25:57

标签: c++ templates c++11 sfinae

我尝试在函数参数上使用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);
}

2 个答案:

答案 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不可扣除。