模板参数,具有类的默认值

时间:2016-04-14 23:34:04

标签: c++ c++11 template-meta-programming sfinae typetraits

我不太明白下面的代码,模板有两个参数,第二个有class = xxxx,这对我来说似乎很奇怪。你能解释一下我该怎么理解它?除了std::enable_if之外,这个c ++ 功能还有其他用例吗?

template < class T,
class = typename std::enable_if<std::is_integral<T>::value>::type>
bool is_even (T i) {return !bool(i%2);}

1 个答案:

答案 0 :(得分:3)

一个字:SFINAE。

替换失败不是错误。

通过谷歌寻找这个词,一个全新的世界将为你打开。

让我们看看代码的含义。

std::is_integral<typename T>::value

它是一个布尔值,取决于类型T,如果true是整数类型,则值为T,否则为false

std::enable_if<bool B, typename T = void>::type

类型TB == true时,否则为其他任何内容。

所以,在你的代码中

template < class T,
class = typename std::enable_if<std::is_integral<T>::value>::type>

T是一个整数类型时,第二个(未命名的)模板参数被替换为一个类型(默认值:void;但是,在这种情况下,确切的类型是无关的)和功能被激活。相反,当T不是整数类型时,替换第二个模板参数失败,并且未激活此is_even()函数版本(对于类型{{1并且,这是重点,它不是错误(可以激活T的另一个版本。)

更有趣的是,可以看到如何为非整数类型实现is_even()的替代版本。您可以认为可以实现另一个否定is_even()

的版本
std::is_integral

但是这不起作用(是一个错误并且不编译),因为你有两个template < class T, class = typename std::enable_if<false == std::is_integral<T>::value>::type> 模板化函数(仅从模板参数的角度来看)与默认参数不同。

解决方案可以将SFINAE应用于返回值

is_even()

通过这种方式,您可以为整数类型启用#include <type_traits> #include <iostream> template <typename T> typename std::enable_if<true == std::is_integral<T>::value, bool>::type is_even (T const & i) { return ! (i%2); } template <typename T> typename std::enable_if<false == std::is_integral<T>::value, bool>::type is_even (T const &) { return false; } int main() { std::cout << "-- is 7 even ? " << is_even(7) << '\n'; std::cout << "-- is 8UL even ? " << is_even(8LL) << '\n'; std::cout << "-- is \"abc\" even ? " << is_even("abc") << '\n'; return 0; } 版本,为非整数类型启用第二个版本(甚至返回is_even())。

p.s:抱歉我的英语不好。