gpt4 book ai didi

c++ - 为什么 `function` 和 `function` 参数类型有时对重载不明确?

转载 作者:行者123 更新时间:2023-12-05 09:26:31 27 4
gpt4 key购买 nike

跟进我的问题 c++ - How do implicit conversions work when using an intermediate type? ,从中我理解了 1 隐式转换最大值的规则,我试图理解涉及函数参数的更高级的用例。

假设我有一个函数,它接受另一个函数作为参数。该函数参数可以返回某些内容,也可以不返回任何内容(void)。因此,我想重载函数定义,在一种情况下接受非 void 函数参数,在另一种情况下接受 void 函数参数。

using VoidType = void (string);
using NonVoidType = string (string);

string call(VoidType *fn, string arg) {
cout << "[using void function]" << endl;
fn(arg);
return arg;
}

string call(NonVoidType *fn, string arg) {
cout << "[using non void function]" << endl;
return fn(arg);
}

调用函数时,给定的参数具有已知类型,因此重载选择应该很简单,例如这里:

void printVoid(string message) {
cout << message << endl;
}

string printNonVoid(string message) {
cout << message << endl;
return message;
}

void test() {
call(printVoid, "call(printVoid)");
call(printNonVoid, "call(printNonVoid)");
}

但当我有中间类型时就不是这样了,比如 std::function 包装器:

string call(function<VoidType> fn, string arg) {
cout << "[using void function]" << endl;
fn(arg);
return arg;
}

string call(function<NonVoidType> fn, string arg) {
cout << "[using non void function]" << endl;
return fn(arg);
}

void test() {
call(printVoid, "call(printVoid)");
call(printNonVoid, "call(printNonVoid)"); // more than one instance of overloaded function "call" matches the argument list:C/C++(308)
}

为此,我在第二次调用时收到错误 more than one instance of overloaded function "call"matches the argument list:C/C++(308)

对此的解决方案是在调用之前显式实例化 std::function:

void test() {
call(function(printNonVoid), "call(function(printNonVoid))");
}

但是,call(function(printNonVoid), "xxx")call(printNonVoid, "xxx") 有何不同?我知道在后一种情况下我会期望隐式转换执行与前一种情况相同的操作。

我是否遗漏了一些东西,比如一些中间的、隐藏的复制构造函数或其他什么?

完整示例:

#include <iostream>

using namespace std;

using VoidType = void (string);
using NonVoidType = string (string);

string callFromPointer(VoidType *fn, string arg) {
cout << "[callFromPointer] void" << endl;
fn(arg);
return "<void>";
}

string callFromPointer(NonVoidType *fn, string arg) {
cout << "[callFromPointer] non void" << endl;
return fn(arg);
}

string callFromFunction(function<VoidType> fn, string arg) {
cout << "[callFromFunction] void" << endl;
fn(arg);
return "<void>";
}

string callFromFunction(function<NonVoidType> fn, string arg) {
cout << "[callFromFunction] non void" << endl;
return fn(arg);
}

void printVoid(string message) { cout << "\t[printVoid] " << message << endl; }
string printNonVoid(string message) {
cout << "\t[printNonVoid] " << message << endl;
return message;
}

void sep() { cout << "\n----\n" << endl; }

void main() {
callFromPointer(printVoid, "callFromPointer(printVoid)");
callFromPointer(printNonVoid, "callFromPointer(printNonVoid)");

sep();

callFromFunction(printVoid, "callFromFunction(printVoid)");
callFromFunction(printNonVoid, "callFromFunction(printNonVoid)"); // more than one instance of overloaded function "callFromFunction" matches the argument list:C/C++(308)

sep();

callFromFunction(function(printVoid), "callFromFunction(function(printVoid))");
callFromFunction(function(printNonVoid), "callFromFunction(function(printNonVoid))");
}

最佳答案

这是因为std::string(*)(std::string)std::function<void(std::string)> 都“兼容”和 std::function<std::string(std::string)>因为前者可以简单地忽略底层函数的返回值。

也就是说,以下两个都是有效的:

std::function<void(std::string)> voidFunc(printNonVoid);
std::function<std::string(std::string)> strFunc(printNonVoid);

由于两者都不是“更好”的匹配项,因此在调用 callFromFunction(printNonVoid, "...") 时重载解析失败。 .


使用 std::function(printNonVoid) 时有效的原因是因为类模板参数推导接管了,并且有一个推导指南T(*)(Args...) -> std::function<T(Args...)> .那条推导转std::function(printNonVoid)进入std::function<std::string(std::string)>(printNonVoid) .因为这是一个完全匹配,不需要对 std::function<std::string(std::string)> 进行转换过载 callFromFunction该重载由重载决议选择。

不过,当仅使用原始函数名称执行重载决策时,该推导指南不会发挥作用,因为函数参数必须显式声明 std::function的模板参数。

关于c++ - 为什么 `function<void (string)>` 和 `function<string (string)>` 参数类型有时对重载不明确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73873635/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com