
[英]Why is call of overloaded 'function(std::string)' is ambiguous?
[英]Why are `function<void (string)>` and `function<string (string)>` parameter types sometimes ambiguous for overloading?
跟進我的問題c++ - 使用中間類型時隱式轉換如何工作? ,從中我了解了1 隱式轉換 max的規則,我試圖了解涉及 function arguments 的更高級用例。
假設我有一個 function,它接受另一個 function 作為參數。 該 function 參數可以返回某些內容,也可以不返回任何內容(無效)。 因此,我想重載 function 定義,在一種情況下接受非 void function 參數,在另一種情況下接受 void function 參數。
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);
}
當調用 function 時,給定的參數具有已知類型,因此重載選擇應該很簡單,例如這里:
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)>
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)
時起作用的原因是因為 class 模板參數推導接管了,並且有一個T(*)(Args...) -> std::function<T(Args...)>
. 該演繹指南將std::function(printNonVoid)
變成std::function<std::string(std::string)>(printNonVoid)
。 因為這是一個完全匹配,不需要轉換std::function<std::string(std::string)>
callFromFunction
的重載,重載是由重載決議選擇的。
That deduction guide doesn't come into play when performing overload resolution with just the raw function name though, since the function arguments have to explicitly declare std::function
's template argument.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.