std :: enable_if如何工作?

时间:2014-08-13 11:05:23

标签: c++ templates c++11 enable-if

我刚问过这个问题: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(); }

2 个答案:

答案 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 Condtrue时定义。

现在有了对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");
                       ^