簡體   English   中英

std :: function作為模板參數

[英]std::function as template parameter

我目前有一個map<int, std::wstring> ,但為了靈活性,我希望能夠分配一個lambda表達式,在地圖中返回std::wstring作為值。

所以我創建了這個模板類:

template <typename T>
class ValueOrFunction
{
private:
    std::function<T()> m_func;
public:
    ValueOrFunction() : m_func(std::function<T()>()) {}
    ValueOrFunction(std::function<T()> func) : m_func(func) {}
    T operator()() { return m_func(); }
    ValueOrFunction& operator= (const T& other)
    {
        m_func = [other]() -> T { return other; };
        return *this;
    }
};

並使用它像:

typedef ValueOrFunction<std::wstring> ConfigurationValue;
std::map<int, ConfigurationValue> mymap;

mymap[123] = ConfigurationValue([]() -> std::wstring { return L"test"; });
mymap[124] = L"blablabla";
std::wcout << mymap[123]().c_str() << std::endl; // outputs "test"
std::wcout << mymap[124]().c_str() << std::endl; // outputs "blablabla"

現在,我不想使用構造函數來包裝lambda,所以我決定添加第二個賦值運算符,這次是std::function

ValueOrFunction& operator= (const std::function<T()>& other)
{
    m_func = other;
    return *this;
}

這是編譯器開始抱怨的地方。 mymap[124] = L"blablabla"; 突然導致這個錯誤:

錯誤C2593:'operator = is ambiguous'

IntelliSense提供了更多信息:

多個運算符“=”匹配這些操作數:function“ValueOrFunction :: operator =(const std :: function&other)[with T = std :: wstring]”function“ValueOrFunction :: operator =(const T&other)[with T = std :: wstring]“操作數類型是:ConfigurationValue = const wchar_t [10] c:\\ projects \\ beta \\ CppTest \\ CppTest \\ CppTest.cpp 37 13 CppTest

所以,我的問題是,為什么編譯器能夠區分std::function<T()>T 我該如何解決這個問題?

基本問題是std::function有一個貪婪的隱式構造函數,它會嘗試轉換任何東西 ,而且只能在正文中編譯。 因此,如果你想重載它,或者不允許轉換為替代方案,你需要禁用可以轉換為替代方法來調用std::function重載的東西。

最簡單的技術是標簽調度。 使operator=貪婪並設置為完美轉發,然后手動調度到帶有標記的assign方法:

 template<typename U>
 void operator=(U&&u){
   assign(std::forward<U>(u), std::is_convertible<U, std::wstring>());
 }
 void assign(std::wstring, std::true_type /*assign_to_string*/);
 void assign(std::function<blah>, std::false_type /*assign_to_non_string*/);

基本上我們正在做手動重載決議。

更先進的技術:(可能不需要)

另一種方法是限制std::function = SFINAE對被調用的參數是有效的,但這更加混亂。

如果你有多種不同的類型與你的std::function競爭,你不得不遺憾地手動調度所有這些類型。 解決這個問題的方法是測試你的類型U是否可以無需調用,結果可以轉換為T ,然后標記為dispatch。 將非std::function重載粘貼在備用分支中,讓其他一切通常更傳統的重載。

有一個細微的區別在於,一個可轉換為std::wstring和callable的std::wstring返回可轉換為T東西,最終被分派到不同於上述原始簡單解決方案的重載,因為所使用的測試實際上並不是互斥的。 對於C ++重載的完全手動模擬(針對std::function s stupidity進行了更正),你需要使這種情況模糊不清!

最后一個高級操作是使用auto和尾隨返回類型來提高其他代碼檢測您的=是否有效的能力。 就個人而言,我不會在C ++ 14之前做到這一點,除非在脅迫之下,除非我正在編寫一些嚴肅的庫代碼。

std::functionstd::wstring都有轉換運算符,可以使用你傳遞的文字寬字符串。 在這兩種情況下,轉換都是用戶定義的,因此轉換序列具有相同的優先級,從而導致歧義。 這是錯誤的根本原因。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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