为什么函数参数的类型推导优先于模板中的类型?

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;
};
  1. 在这里,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
  1. 但这里的事情对我来说有点不明确,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)