簡體   English   中英

使用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

該代碼工作得很好。 所以我只是想知道:

  1. 為什么普通函數指針類型的推導比標准模板的推導“強”?
  2. 是否有某種解決方法仍可以使用更通用的版本,而不是手動強制轉換參數?

編譯器是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函數的實現細節,因此我省略了這些實現。 由於您似乎只想支持voidbool返回類型,因此我添加了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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM