当前位置: 首页 > 知识库问答 >
问题:

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

东门俊民
2023-03-14

这是在参数是重载函数时重载解析如何工作中提到的更复杂的问题?

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

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的编译都失败了。

它可以用重载解析/模板参数推导规则来解释,还是应该在这些编译器中被限定为缺陷?

共有1个答案

农飞星
2023-03-14

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

[temp.decrete.call]/6:P是函数类型、函数类型指针或成员函数类型指针时的

— 如果参数是包含一个或多个函数模板的重载集,则该参数将被视为非演绎上下文。

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

< code >[temp . deduct . type]/4:[...]如果模板参数只在非推导的上下文中使用,并且没有显式指定,则模板参数推导将失败。

这个失败的扣除会给你你的错误。请注意,如果显式指定参数,代码将成功编译:

bar<int,double>(foo);

现场演示

 类似资料:
  • 假设有一个模板函数 接受任意数量的参数。给定最后一个参数始终是 ,我如何实现下面显示的 模板,以便 包含此 的参数? 例如,如果像这样调用,应该是: 我的第一个想法是: 但这不会编译: 问题一: 为什么这不能编译?为什么模板参数演绎失败? 最终,我想出了这个解决方案: 这里,是,即中的最后一种类型。然后,的临时值被传递到,其中。这行得通,但在我看来很难看。 问题二: 我想知道如果没有两个函数和的临

  • 我目前有一个,但是为了灵活性,我希望能够分配一个lambda表达式,将作为映射中的值返回。 所以我创建了这个模板类: 并像这样使用它: IntelliSense提供了更多信息: 多个操作符“=”匹配这些操作数:function“valueorfunction::operator=(const std::function&other)[with T=std::wstring]”function“va

  • 如果我没有理解错的话,类模板定义了一个函数,所以当我调用时,编译器有可能进行隐式强制转换,但是在函数模板的情况下,此时没有函数定义,所以隐式强制转换不会发生。 但我不明白为什么编译器不能创建函数定义,然后应用隐式强制转换? 错误是: 在函数“int main()”中:    25:24:错误:调用“test2::add(void(&)(int))”没有匹配函数    25:24:注:候选人是:  

  • 这些代码如下: 使用G++4.8.2错误信息编译:

  • 标准中似乎没有规则提到模板参数需要默认参数的情况。 在dcl中。fct。默认值#1 如果在参数声明中指定了初始化子句,则将此初始化子句用作默认参数。缺省参数将用于缺少尾随参数的调用。 在本节中,规则明确描述了何时为函数调用提供默认参数。但是,我在标准中没有找到与上面描述何时提供默认参数作为模板参数的语句类似的引用。 例如

  • N4527 14.8.2.4[温度扣除部分] 3用于确定排序的类型取决于进行部分排序的上下文: (3.1)-在函数调用的上下文中,使用的类型是那些函数调用具有参数的函数参数类型。 (3.2)-在调用转换函数的上下文中,使用转换函数模板的返回类型。 (3.3)-在其他上下文(14.5.6.2)中使用函数模板的函数类型。 4以上从参数模板中指定的每种类型以及从参数模板中指定的相应类型都用作P和A的类型