如何解决std::unordered_map 中的 std::function,错误 C3867 非标准语法;使用“&”创建指向成员的指针
我尝试通过使用地图调用某些 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 会出现问题
解决方法
我认为为此使用 pointers-to-members。 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::map
比 std::unordered_map
快。检查以确保。 (Live demo)
没有说的部分(除了一些回复)是你试图调用成员函数,并且要求你有一个指针(或引用,或其他)到您正在调用的类实例。如果您愿意,您可以将其打包到您的地图中。在这种情况下,您不需要这样做,因为您的地图“存在于”班级中,因此您不必这样做,但如果您愿意,这里有一种方法可以做到。
我采用了 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,std::bind(&MyClass::InfoInquiry,this,std::placeholders::_1,std::placeholders::_2)},std::bind(&MyClass::ActivateDeactivate,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_c2) << "\n";
std::cout << c.Call("X",local_c2) << "\n";
}
这保留了通过使用 std::bind
来调用具有任意参数的方法的能力,以创建具有您想要的签名的可调用函数,同时还保留指向您的实例的指针。如果你曾经在你的班级之外这样做,请确保你不要使用悬空指针。在这里,使用 this
并且您的地图与您的类一样长,但是如果您的 bind
目标是另一个类,请确保它不指向不再存在的对象尝试调用它。
错误状态,该怎么做。但它只适用于那么简单的静态函数。
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::ActivateDeactivate},};
};
因为 m_ApiCalbacks
是 const,所以使用静态成员函数是有意义的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。