c++ - 当重载函数作为参数涉及时,模板参数推导如何工作?

标签 c++ language-lawyer overload-resolution template-argument-deduction

这是How does overload resolution work when an argument is an overloaded function? 中提到的更复杂的问题

以下代码 compiles without any problem :

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);
}

模板参数推导似乎不是一项具有挑战性的任务 - 只有一个函数 foo() 接受两个参数。但是,取消注释 foo() 的模板重载(它仍然只有一个参数)会无缘无故地中断编译。 gcc 5.x/6.x 和 clang 3.9 编译都失败。

是否可以通过重载解析/模板参数推导的规则来解释,或者它应该被定义为那些编译器中的缺陷?

最佳答案

如您对链接问题的回答中所述:

[temp.deduct.call]/6:When P is a function type, pointer to function type, or pointer to member function type:

— If the argument is an overload set containing one or more function templates, the parameter is treated as a non-deduced context.

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

[temp.deduct.type]/4: [...]If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.

而这个失败的推论给了你你的错误。请注意,如果您显式指定参数,则代码编译成功:

bar<int,double>(foo);

Live demo

关于c++ - 当重载函数作为参数涉及时,模板参数推导如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40356990/

相关文章:

c++ - 将重载的 CRTP 类成员方法传递给 lambda

c++ - 重载运算符或数字转换的问题

c++ - 错误 : no viable overloading with clang, 用 gcc 编译

python - 删除 *a : can't use starred expression here

c++ - 标签调度对象是否实际实例化?

c++ - C++ 模板的问题(大惊喜!)。为什么这行不通?

c++ - OpenGL,如何旋转彼此独立的对象?

c++ - 当非常量方法是私有(private)的时,为什么不调用公共(public) const 方法?

c++ - Clang 上的重载运算符歧义,但 GCC 上没有,哪个是正确的?

c++ - 如何在opencv C++中找到最大的轮廓