std::function in std::unordered_map, error C3867 非标准语法;使用“&”创建指向成员的指针
std::function in std::unordered_map, error C3867 non-standard syntax; use '&' to create a pointer to member
我尝试用地图调用一些 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 会遇到问题
错误状态,该怎么做。但它只适用于简单的静态函数。
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
是常量,使用静态成员函数是有意义的。
我赞成为此使用 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)
部分没有说明(除了某些回复)是您正在尝试调用成员函数,并且要求您有一个指针(或引用,或其他)到您正在调用的 class 实例。如果您愿意,您 可以 将其包装到您的地图中。在这种情况下,您不需要这样做,因为您的地图“存在于”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
来调用具有任意参数的方法的能力,以创建具有您想要的签名的可调用函数,同时还保留指向您的实例的指针。但是,如果您曾在 class 的 外部 执行此操作,请确保您没有使用悬挂指针。在这里,使用 this
并且您的地图与您的 class 一样长,但如果您的 bind
目标是另一个 class,请确保它不指向对象当您尝试调用它时,它不再存在。
我尝试用地图调用一些 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 会遇到问题
错误状态,该怎么做。但它只适用于简单的静态函数。
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
是常量,使用静态成员函数是有意义的。
我赞成为此使用 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)
部分没有说明(除了某些回复)是您正在尝试调用成员函数,并且要求您有一个指针(或引用,或其他)到您正在调用的 class 实例。如果您愿意,您 可以 将其包装到您的地图中。在这种情况下,您不需要这样做,因为您的地图“存在于”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
来调用具有任意参数的方法的能力,以创建具有您想要的签名的可调用函数,同时还保留指向您的实例的指针。但是,如果您曾在 class 的 外部 执行此操作,请确保您没有使用悬挂指针。在这里,使用 this
并且您的地图与您的 class 一样长,但如果您的 bind
目标是另一个 class,请确保它不指向对象当您尝试调用它时,它不再存在。