简体   繁体   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

I try to replace if/else by using a map to call some api我尝试通过使用 map 调用一些 api 来替换if/else

why the initializer list throws the error?为什么初始化列表会抛出错误?

...
#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},
      ...
   };
}

note: static is not allowed in this case because it's in a dll and reloading the dll gets problems注意: static在这种情况下是不允许的,因为它在 dll 中并重新加载 dll 会出现问题

I would argue for using pointers-to-members for this.我会主张为此使用指向成员的指针。 std::function comes with a cost (at least one extra indirection, ie slow). std::function是有代价的(至少一个额外的间接,即慢)。

Something like this (edited for brevity):像这样的东西(为简洁而编辑):

#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";
}

Bonus note: in some C++ implementations, std::map is faster than std::unordered_map .额外说明:在某些 C++ 实现中, std::mapstd::unordered_map快。 Check to be sure.检查确定。 ( Live demo ) 现场演示

Part of what isn't said (except in some replies) is that you're trying to call member functions, and that requires you to have a pointer (or reference, or whatever) to the class instance you're calling.未提及的部分内容(某些回复除外)是您正在尝试调用成员函数,这需要您拥有指向您正在调用的 class 实例的指针(或引用,或其他)。 You can wrap that up into your map if you wish.如果你愿意,你可以把它包装到你的 map 中。 You don't need to in this case, as your map "lives" inside the class, and thus you don't have to, but here's a way to do it if you'd like.在这种情况下,您不需要这样做,因为您的 map “生活”在 class 内部,因此您不必这样做,但如果您愿意,可以使用以下方法。

I'm taking rustyx's implementation, and changing it slightly to show another way of doing this, preserving your original signatures of the callee methods.我正在采用 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";
}

This preserves the ability to call the methods with arbitrary arguments through the usage of std::bind to make a callable function that has the signature you want, while also keeping a pointer to your instance.这保留了通过使用std::bind来调用具有任意 arguments 的方法的能力,以创建具有所需签名的可调用 function,同时还保留指向您的实例的指针。 If you ever do this outside of your class though, be sure you don't use a dangling pointer.但是,如果您曾经在 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. 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.

The error states, what to do.错误说明,该怎么做。 But it only works on static functions that simple.但它只适用于简单的 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},
    };
};

Since m_ApiCalbacks is const, using static member functions makes sense.由于m_ApiCalbacks是 const,因此使用 static 成员函数是有意义的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C3867:&#39;_com_error :: Description&#39;:非标准语法 使用“&”创建指向成员的指针 - C3867 : '_com_error::Description': non-standard syntax; use '&' to create a pointer to member c3867&#39;sf::Time::as seconds&#39;:非标准语法;使用&#39;&amp;&#39;创建指向成员的指针 - c3867'sf::Time::as seconds':non-standard syntax ;use '&'to create a pointer to a member Visual Studio 2015 错误 C3867 &#39;Rectangle::get_area&#39;:非标准语法; 使用“&amp;”创建指向成员的指针 - Visual Studio 2015 Error C3867 'Rectangle::get_area': non-standard syntax; use '&' to create a pointer to member “错误C3867:非标准语法; 使用虚拟流操纵器时,使用“&”创建指向成员的指针” - “Error C3867: non-standard syntax; use '&' to create a pointer to member” when using virtual stream manipulator 错误1错误C3867:&#39;Command :: getSecondWord&#39;:函数调用缺少参数列表; 使用“&”创建指向成员的指针 - Error 1 error C3867: 'Command::getSecondWord': function call missing argument list; use '&' to create a pointer to member “的std :: basic_string的 <char,std::char_traits<char> ,性病::分配器 <char> &gt; :: c_str&#39;:非标准语法; 使用&#39;&&#39;创建指向成员的指针 - 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>::c_str': non-standard syntax; use '&' to create a pointer to member 获取错误:C3867 &#39;Template_class<int> ::add&#39;: 非标准语法; 使用带有模板的函数指针时 - Getting error : C3867 'Template_class<int>::add': non-standard syntax; when using pointers to functions with templates 非标准语法; 使用 '&amp;' 创建指向成员 C++ 的指针 - non-standard syntax; use '&' to create a pointer to member C++ 错误信息:非标准语法; 使用“&amp;”创建指向成员的指针 - Error Message: non-standard syntax; use '&' to create a pointer to member 非标准语法; 将成员函数分配给vector时,使用&#39;&&#39;创建指向成员错误的指针 - non-standard syntax; use '&' to create a pointer to member error when assigning member function to vector
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM