为什么函数参数的类型推导优先于模板中的类型?
Why type deduction of function parameters are prioritized over the types from template?
让我们看一下 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 integral\n";
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)
让我们看一下 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 integral\n";
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)