簡體   English   中英

如何在C ++中重載std :: function簽名

[英]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.

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