簡體   English   中英

std::unordered_map 中的 std::function,錯誤 C3867 非標准語法; 使用 '&' 創建指向成員的指針

[英]std::function in std::unordered_map, error C3867 non-standard syntax; use '&' to create a pointer to member

我嘗試通過使用 map 調用一些 api 來替換if/else

為什么初始化列表會拋出錯誤?

...
#include <functional>
#include <unordered_map>

class MyClass final : public Base
{
   std::string InfoInquiry(Class_1& request, Class_2& response);
   std::string ActivateDeactivate(Class_1& request, Class_2& response);
   ...
   using Callback = std::function<std::string(Class_1&, Class_2&)>;
   const std::unordered_map<std::string, Callback> m_ApiCalbacks{ //error C3867: 'MyClass ::InfoInquiry': non-standard syntax; use '&' to create a pointer to member
      {"INFO", InfoInquiry},
      {"ACTIVATE_DEACTIVATE", ActivateDeactivate},
      ...
   };
}

注意: static在這種情況下是不允許的,因為它在 dll 中並重新加載 dll 會出現問題

我會主張為此使用指向成員的指針。 std::function是有代價的(至少一個額外的間接,即慢)。

像這樣的東西(為簡潔而編輯):

#include <functional>
#include <map>
#include <iostream>

class MyClass
{
public:
    std::string InfoInquiry() { return "info!"; }
    std::string ActivateDeactivate() { return "activate!"; }
    using Callback = std::string (MyClass::*) ();
    const std::map<std::string, Callback> m_ApiCalbacks {
       {"INFO", &MyClass::InfoInquiry},
       {"ACTIVATE_DEACTIVATE", &MyClass::ActivateDeactivate}
    };
    std::string Call(std::string const& name) {
        auto it = m_ApiCalbacks.find(name);
        if (it == m_ApiCalbacks.end()) // optional check if name is valid
            return "???";
        return (this->*(it->second))();
    }
};

int main() {
    MyClass c;
    std::cout << c.Call("INFO") << "\n";
    std::cout << c.Call("ACTIVATE_DEACTIVATE") << "\n";
    std::cout << c.Call("X") << "\n";
}

額外說明:在某些 C++ 實現中, std::mapstd::unordered_map快。 檢查確定。 現場演示

未提及的部分內容(某些回復除外)是您正在嘗試調用成員函數,這需要您擁有指向您正在調用的 class 實例的指針(或引用,或其他)。 如果你願意,你可以把它包裝到你的 map 中。 在這種情況下,您不需要這樣做,因為您的 map “生活”在 class 內部,因此您不必這樣做,但如果您願意,可以使用以下方法。

我正在采用 rustyx 的實現,並稍微改變它以顯示另一種方法,保留你原來的被調用方法簽名。

#include <functional>
#include <map>
#include <iostream>

class MyClass
{
public:
    std::string InfoInquiry(Class_1& request, Class_2& response) { return "info!"; }
    std::string ActivateDeactivate(Class_1& request, Class_2& response) { return "activate!"; }
    using Callback = std::function<std::string(Class_1&, Class_2&)>;
    const std::map<std::string, Callback> m_ApiCalbacks {
       {"INFO", std::bind(&MyClass::InfoInquiry, this, std::placeholders::_1, std::placeholders::_2)},
       {"ACTIVATE_DEACTIVATE", std::bind(&MyClass::ActivateDeactivate, this, std::placeholders::_1, std::placeholders::_2)}
    };
    std::string Call(std::string const& name, Class_1& c1, Class_2& c2) {
        auto it = m_ApiCalbacks.find(name);
        if (it == m_ApiCalbacks.end()) // optional check if name is valid
            return "???";
        return (it->second)(c1, c2);
    }
};

int main() {
    MyClass c;
    Class_1 local_c1{};
    Class_2 local_c2{};
    std::cout << c.Call("INFO", local_c1, local_c2) << "\n";
    std::cout << c.Call("ACTIVATE_DEACTIVATE", local_c1, local_c2) << "\n";
    std::cout << c.Call("X", local_c1, local_c2) << "\n";
}

這保留了通過使用std::bind來調用具有任意 arguments 的方法的能力,以創建具有所需簽名的可調用 function,同時還保留指向您的實例的指針。 但是,如果您曾經在 class之外執行此操作,請確保不要使用懸空指針。 Here, this is used and your map lives as long as your class, but if your bind target is another class, make sure it doesn't point to an object that doesn't exist anymore when you try and call it.

錯誤說明,該怎么做。 但它只適用於簡單的 static 功能。

class MyClass : public Base {
    static std::string InfoInquiry(Class_1& request, Class_2& response);
    static std::string ActivateDeactivate(Class_1& request, Class_2& response);

    using Callback = std::function<std::string(Class_1&, Class_2&)>;
    const std::unordered_map<std::string, Callback> m_ApiCalbacks {
        {"INFO", &MyClass::InfoInquiry},
        {"ACTIVATE_DEACTIVATE", &MyClass::ActivateDeactivate},
    };
};

由於m_ApiCalbacks是 const,因此使用 static 成員函數是有意義的。

暫無
暫無

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

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