让我们看看enable_if
使用的简单示例
template <bool, typename T = void>
struct enable_if
{
};
template <typename T>
struct enable_if<true, T>
{
typedef T type;
};
- 这里预期
y
将是int
,因为T
是我们的";启用";类型
template <typename T, typename Y = typename std::enable_if<std::is_integral<T>::value, T>::type>
void do_stuff(T t)
{
(void)t;
Y y;
std::cout << typeid(y).name() << std::endl;
}
do_stuff(15); // int
- 但这里的情况对我来说有些不明确,
y
将被推导为实际参数的类型
template <typename T, typename Y = typename std::enable_if<std::is_integral<T>::value, T>::type>
void do_stuff(T t, Y y)
{
(void)t;
std::cout << "do_stuff integraln";
std::cout << typeid(y).name() << std::endl;
}
do_stuff(15, 14.3); // double
所以我的问题是:
什么规则会迫使编译器从传递的实际参数中优先推导y
,而忽略enable_if
中启用的type
?
只有在未显式指定模板参数且无法推导模板参数时,才使用默认模板参数。在这种情况下,Y
可以从14.3
推导为double
,那么就不会使用默认参数。类似地,在第一个示例中,您也可以通过指定模板参数来绕过对std::enable_if
的检查。
do_stuff<int, double>(15); // double
顺便说一句,您可以在类型声明中使用std::enable_if
添加非类型模板参数,使检查始终生效。
template <typename T, typename Y, typename std::enable_if<std::is_integral<T>::value, T>::type* = nullptr>
void do_stuff(T t, Y y)