[英]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::map
比std::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.