std :: enable_if如何工作?

Jon*_*Mee 13 c++ templates enable-if c++11

我刚问了这个问题:std :: numeric_limits作为一个条件

我理解用于std::enable_if定义有条件地导致该方法无法编译的方法的返回类型的用法.

template<typename T>
typename std::enable_if<std::numeric_limits<T>::is_integer, void>::type foo(const T &bar) { isInt(bar); }
Run Code Online (Sandbox Code Playgroud)

我不明白的是第二个参数和看似无意义的赋值,std::enable_if当它被声明为模板语句的一部分时,如Rapptz的 回答.

template<typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
void foo(const T& bar) { isInt(); }
Run Code Online (Sandbox Code Playgroud)

Jon*_*Mee 15

正如40two评论中所提到的,理解替换失败不是错误是理解的先决条件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; };
Run Code Online (Sandbox Code Playgroud)

这里的关键之处在于,事实上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); }
Run Code Online (Sandbox Code Playgroud)

正如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作为条件


fir*_*rda 6

template<typename T, std::enable_if<std::is_integral<T>::value, int>::type = 0>
void foo(const T& bar) { isInt(); }
Run Code Online (Sandbox Code Playgroud)

如果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");
}
Run Code Online (Sandbox Code Playgroud)
错误:没有匹配的函数调用'foo(const char [4])'
  foo("坏"); 酒吧(“坏”);
           ^
注意:候选人是:
注意:template::value, int>::type > void foo(const T&)
 void foo(const T& bar) {}
      ^
注意:模板参数推导/替换失败:
错误:在“struct std::enable_if”中没有名为“type”的类型
 模板::值,整数>::type = 0>
                                                                                       ^
注意:无效的模板非类型参数
错误:没有匹配的函数调用'bar(const char [4])'
  foo("坏"); 酒吧(“坏”);
                       ^