[英]How can I use templates to deduce the parameter types of a std::function?
[英]Compiler fails to deduce types when using std::function
因此,我為類編寫了一個方法及其重載,如下所示:
bool my_for_each(someIterator begin, someIterator end, bool (*_lambda)(someIterator));
void my_for_each(someIterator begin, someIterator end, void (*_lambda)(someIterator));
如您所見,唯一的區別是傳遞的函數的簽名,即其返回類型。 雖然上面的代碼在我調用時工作得很好:
my_for_each(iteratorBegin, iteratorEnd, [](someIterator) {; }); // calls void version
my_for_each(iteratorBegin, iteratorEnd, [](someIterator)->bool {return false; }); // calls bool version
...,如果我將my_for_each函數編寫如下:
bool my_for_each(someIterator begin, someIterator end, std::function<bool(someIterator)> _lambda);
void my_for_each(someIterator begin, someIterator end, std::function<void(someIterator)> _lambda);
如果我以相同的方式調用函數(C2668對重載函數的模棱兩可的調用),代碼將無法編譯。 雖然,如果我手動轉換函數:
my_for_each(iteratorBegin, iteratorEnd, static_cast<std::function<void(someIterator)>>([](someIterator) {; })); //calls void version
my_for_each(iteratorBegin, iteratorEnd, static_cast<std::function<bool(someIterator)>>([](someIterator) -> bool { return false; })); //calls bool version
該代碼工作得很好。 所以我只是想知道:
編譯器是VS2015。
感謝,並有一個愉快的一天!
std::function
和lambda具有不同的類型,這意味着第二個示例需要從lambda的類型隱式轉換為std::function
。
問題在於返回bool
的lambda可以隱式轉換為std::function<bool(T)>
和std::function<void(T)>
,因此這兩個重載對於您的調用都是同等有效的選擇,從而導致模糊性錯誤。 當您手動將它們std::function
轉換為適當的std::function
,明確解決了歧義。
編輯:解決方法
您可以通過提供一個附加的模板重載來解決此問題,該重載接受任何類型的可調用類型,推導該可調用類型的返回類型,並自動執行強制類型轉換。 為了通用someIterator
,我已經將someIterator
更改為模板參數。 由於您尚未提供my_for_each
函數的實現細節,因此我省略了這些實現。 由於您似乎只想支持void
和bool
返回類型,因此我添加了static_assert
來生成明確的編譯器錯誤,以防提供不受支持的返回類型。
#include <functional>
#include <type_traits>
// Implement for std::function<bool(iter)>
template<class I>
bool my_for_each(I begin, I end, std::function<bool(I)> lambda);
// Implement for std::function<void(iter)>
template<class I>
void my_for_each(I begin, I end, std::function<void(I)> lambda);
// Dispatch to the right overload
template<class T, class I>
auto my_for_each(I begin, I end, T&& lambda)
{
using return_type = decltype(lambda(begin)); // Obtain the return type of lambda
static_assert(std::is_same<return_type, bool>::value || std::is_same<return_type, void>::value,
"my_for_each only accepts function objects that return void or bool");
using function_type = std::function<return_type(I)>; // The type to cast lambda to
return my_for_each(begin, end, function_type(std::forward<T>(lambda))); // Preform the cast
}
原因是這樣的事實,非捕獲的lambda只可轉換為將接受使用類型的參數的函數指針。
另一方面, std::function
具有接受所有內容的模板化構造std::function
。 因此,可以從您的lambda創建std::function<bool...>
和std::function<void ...>
來實現my_for_each
重載解析。 (請注意,但是無法創建這些對象)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.