具有不同参数的成员函数的映射
std::map of member functions with different args
我有一个DeviceSettingsManager
类,看起来像:
class DeviceSettingsManager
{
int32_t PropertyA();
void SetPropertyA(int32_t prop);
std::string PropertyB();
void SetPropertyB(std::string prop);
// about 50 properties go here ...
}
,我需要根据我拥有的属性字符串设置属性。没有这样的代码:
// Parse property string ("PropertyA = 100, PropertyB = xyz, ...") to key/value pairs
if (key == "PropertyA")
manager.SetPropertyA(value);
else if (key == "PropertyB")
manager.SetPropertyB(value);
// 50 more properties ...
不是很好,对吧?
第一个想法是在map中存储setter:
setters_[key](value); // where for example key == "PropertyA" and value = 100
但是有一个问题:我不能在一个map中存储不同的函子:
typedef boost::function<void(int32_t)> setter_int_t;
typedef boost::function<void(std::string)> setter_string_t;
std::map<std::string, ???> setters_;
当然,我可以有两个映射(int32_t
和std::string
)。但它不能很好地扩展。如果我将被迫添加新的setter参数类型,如float
或double
甚至user_defined_class
,我将需要更多的映射。
另一种方法是使用boost::any
,在这种情况下,我需要将reinterpret_cast
返回到我需要的boost::function
,因此再次面对问题。
问题是:我如何管理这样的PropertyManagers,以防止编写数十亿if-else语句?
最后的做法(不知道是不是最好的做法):
// checks (map.find(...)) omitted for brevity
struct base_type_holder
{
virtual ~base_type_holder() {};
};
template<typename T>
struct type_holder : base_type_holder
{
typedef T type;
};
std::map<std::string, boost::shared_ptr<base_type_holder> > types_;
template<typename T>
void RegisterSetterType(const std::string& name)
{
types_[name].reset(new type_holder<T>);
}
boost::shared_ptr<base_type_holder> GetSetterType(const std::string& name)
{
return types_[name];
}
template<typename T>
std::map<std::string, boost::function<void(T)> >& SettersMap()
{
static std::map<std::string, boost::function<void(T)> > settersMap;
return settersMap;
}
template<typename T, typename H>
void AddSetter(const std::string& name, void (H::*Setter)(T))
{
static H settingsManager;
RegisterSetterType<T>(name);
SettersMap<T>()[name] = boost::bind(Setter, &settingsManager, ::_1);
}
void CallSetter(const std::string& name, const std::string& value)
{
boost::shared_ptr<base_type_holder> base_type = GetSetterType(name);
if (dynamic_cast<type_holder<int32_t> *>(base_type.get()))
{
SettersMap<int32_t>()[name](atoi(value.c_str()));
}
else if (dynamic_cast<type_holder<std::string> *>(base_type.get()))
{
SettersMap<std::string>()[name](value);
}
}
// Now somewhere in .cpp
AddSetter<int32_t, DeviceSettingsManager>("PropertyA", &DeviceSettingsManager::SetPropertyA);
AddSetter<const std::string&, DeviceSettingsManager>("PropertyB", &DeviceSettingsManager::SetPropertyB);
// other...
// later
CallSetter(key, value); // key = "PropertyA", value = "100"
可以只是制作<key, parser>
的地图吗?并将初始字符串、位置和管理器对象传递给解析器。它比一堆映射更灵活,但您仍然需要用具体的解析器填充map。
相关文章:
- 将函数类成员映射到类本身内部
- 添加静态constexpr成员是否会更改结构/类的内存映射
- 整数键映射到头文件中的成员函数指针
- C++预处理会生成变量成员、资源库和映射
- 迭代嵌套映射与范围为循环:没有名为"first"的成员
- C++:在子类中扩展静态 STL 容器/映射成员?
- 用于对项目进行分组并将单个项目映射到其他组成员的数据结构
- C++-将对象(如字符串)映射到表中成员函数的正确方法
- 重构MFC消息映射以包括完全限定的成员函数指针
- gdb映射显示不正确的成员变量
- c++ 嵌套结构映射找不到成员
- 尝试通过指针映射访问类成员
- 映射类的数据成员
- std::映射键作为模板化结构与枚举成员
- 为什么擦除C++映射类成员中的值?
- 如何创建<id,成员函数>的映射?
- 向量映射作为实例成员的C 地图
- 如何使用成员函数映射参数包?(非恢复性,折叠前表达式)
- 删除类成员映射时,映射析构函数stl_map.h崩溃
- 在类定义中初始化静态常量成员映射<>