当重载函数作为参数参与时,模板参数推导如何工作?

Leo*_*eon 21 c++ language-lawyer overload-resolution argument-deduction

这是一个更复杂的问题,如果参数是一个重载函数,重载决策是如何工作的?

下面的代码编译没有任何问题:

void foo() {}
void foo(int) {}
void foo(double) {}
void foo(int, double) {}

// Uncommenting below line break compilation
//template<class T> void foo(T) {}

template<class X, class Y> void bar(void (*f)(X, Y))
{
    f(X(), Y());
}

int main()
{
    bar(foo);
}
Run Code Online (Sandbox Code Playgroud)

模板参数推导似乎不是一项具有挑战性的任务 - 只有一个函数foo()接受两个参数.但是,取消注释模板重载foo()(仍然只有一个参数)会破坏编译,没有明显的原因.使用gcc 5.x/6.x和clang 3.9编译失败.

可以通过重载决策/模板参数推导的规则来解释它还是应该被认为是那些编译器中的缺陷?

Tar*_*ama 20

如您在链接问题的答案中所述:

[temp.deduct.call]/6:何时P是函数类型,指向函数类型的指针或指向成员函数类型的指针:

- 如果参数是包含一个或多个函数模板的重载集,则该参数将被视为非推导的上下文.

由于重载集包含函数模板,因此该参数被视为非推导的上下文.这会导致模板参数推断失败:

[temp.deduct.type]/4: [...]如果模板参数仅在非推导的上下文中使用且未明确指定,则模板参数推断将失败.

这次失败的演绎会给你错误.请注意,如果您显式指定参数,则代码将成功编译:

bar<int,double>(foo);
Run Code Online (Sandbox Code Playgroud)

现场演示