我刚问过这个问题:std::numeric_limits as a Condition
我理解std::enable_if
将定义有条件地导致方法无法编译的方法的返回类型的用法。
template<typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer, void>::type foo(const T &bar) { isInt(bar); }
我不理解的是std::enable_if
当它被声明为模板语句的一部分时的第二个参数和看似无意义的赋值,如Rapptz answer。
template<typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
void foo(const T& bar) { isInt(); }
答案 0 :(得分:11)
正如40two的评论中所提到的,理解Substitution Failure Is Not An Error是理解std::enable_if
的先决条件。
std::enable_if
是一个专门的模板,定义为:
template<bool Cond, class T = void> struct enable_if {};
template<class T> struct enable_if<true, T> { typedef T type; };
这里的关键是typedef T type
仅在bool Cond
为true
时定义。
现在有了对std::enable_if
的理解,很明显void foo(const T &bar) { isInt(bar); }
的定义是:
template<typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer, void>::type foo(const T &bar) { isInt(bar); }
如firda所述,= 0
是第二个模板参数的默认值。默认template<typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
的原因是可以使用foo< int >( 1 );
调用这两个选项。如果std::enable_if
模板参数未默认,则调用foo
将需要两个模板参数,而不仅仅是int
。
作为2013年之前Visual Studio版本用户的注释,您将无法默认功能模板参数,因此您只能使用第一个定义:std::numeric_limits as a Condition
答案 1 :(得分:4)
template<typename T, std::enable_if<std::is_integral<T>::value, int>::type = 0>
void foo(const T& bar) { isInt(); }
如果T
不是整数,则无法编译(因为enable_if<...>::type
将不会被定义)。它是对foo
函数的保护。赋值= 0
用于默认模板参数来隐藏它。
另一种可能性:(是原始问题中缺少typename
)
#include <type_traits>
template<typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
void foo(const T& bar) {}
template<typename T>
typename std::enable_if<std::is_integral<T>::value>::type
bar(const T& foo) {}
int main() {
foo(1); bar(1);
foo("bad"); bar("bad");
}
error: no matching function for call to ‘foo(const char [4])’ foo("bad"); bar("bad"); ^ note: candidate is: note: template::value, int>::type > void foo(const T&) void foo(const T& bar) {} ^ note: template argument deduction/substitution failed: error: no type named ‘type’ in ‘struct std::enable_if’ template::value, int>::type = 0> ^ note: invalid template non-type parameter error: no matching function for call to ‘bar(const char [4])’ foo("bad"); bar("bad"); ^