[英]How to overload on std::function signature in C++
我知道這個問題之前已被問過,但盡管我是一位經驗豐富的編碼員,但我不理解答案,也沒有辦法回答這些先前的問題,要求澄清。 沒有“回復”鏈接或任何東西。 此外,這些問題還很舊。 所以,我重新問這個問題。
我有一個類,我正在重載+ =運算符。 我想要一個重載來獲取一個裸函數指針,另一個需要一個std :: function:
void operator+=(void (*handler)());
void operator+=(function<void (void *, T)> handler);
用法:
MyClass a;
a += [](){ DoSomething(); };
a += [](void *x, T y){ DoSomething(); };
遺憾的是,代碼無法編譯,因為編譯器無法確定第二個重載是否不適合第一個+ =調用。
如何定義我的operator + =成員函數來糾正這個問題? 我不想改變運算符的使用方式(例如通過使用顯式轉換)。 我希望他們像上面所說的那樣工作。
此外,還有以下過載也很方便:
void operator+=(function<void()> handler);
但同樣,我不能基於函數<>模板的簽名重載。
有關更多示例,請參閱此主題: std :: function的模板參數(簽名)是否是其類型的一部分? (我嘗試實現該線程中提到的各種解決方案, 但沒有一個會編譯 )
我已經用多種語言編程多年了,但我的C ++技能有點生疏。
以下代碼適用於g ++ 4.7.2:
#include <functional>
#include <iostream>
template <typename T>
typename std::enable_if<std::is_convertible<T, void(*)()>::value>::type
foo(T&&)
{
std::cout << "foo(void(*)())" << std::endl;
}
void foo(std::function<void(void*,int)>)
{
std::cout << "foo(std::function<void(void*,int)>)" << std::endl;
}
int main()
{
foo([]{});
foo([](void*,int){});
}
問題是由std::function
的構造std::function
引起的,它被聲明為template <class F> function(F);
。 該構造函數接受所有內容作為其參數。 如果該參數沒有合適的operator()
,則在構造函數的實例化期間會生成錯誤。
不幸的是,重載解析過程不需要實例化任何模板函數,因此編譯器認為所有內容都可以轉換為任何std::function
類型。
好的,如果你有一個std::vector<std::function<void()>>
你甚至不需要一堆重載。 最簡單的方法是定義一個模板化operator+=
,可能“保護” std::enable_if
只能為可調用對象或函數指針打開。 所以傳遞lambdas或原始指針將在assign(push_back / emplace_back)上為你做自動轉換。 傳遞std::function
將按預期分配。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.