通用状态机构造优化:将参数对象名称作为参数传入以直接访问对象
解决方案:用名称-Param映射替代内嵌字符串
看起来你想摆脱Param结构体里冗余的字符串名称,转而直接用Param对象的变量名来作为标识,这样既避免重复输入,也能减少写错名称的风险。下面是一个实用的实现方案,结合C++的初始化列表和宏来实现你的需求:
第一步:重构Param结构体
首先把原来内嵌的std::string name去掉,让Param只保留状态相关的核心数据:
#include <unordered_map> #include <string> #include <initializer_list> struct Param { float float_val; int int_val; char char_val; // 移除原来的string name字段 };
第二步:改造StateMachine类
在StateMachine内部维护一个名称到Param的映射表,同时定义一个辅助结构体来传递"名称-Param"对,构造函数接收初始化列表来批量传入这些配对:
class StateMachine { private: std::unordered_map<std::string, Param> state_map; public: // 辅助结构体:用于绑定名称和Param struct NamedParam { std::string name; Param param; }; // 构造函数接收初始化列表 StateMachine(std::initializer_list<NamedParam> params) { for (const auto& entry : params) { state_map[entry.name] = entry.param; } } // 提供便捷的访问接口 Param& get_state(const std::string& state_name) { return state_map.at(state_name); // 用at()确保存在性,不存在会抛异常 } const Param& get_state(const std::string& state_name) const { return state_map.at(state_name); } };
第三步:用宏简化名称绑定
为了避免手动输入变量名的字符串(比如把state1写成"state1"),我们可以用一个宏自动将变量名转换为字符串:
#define BIND_STATE(state_var) {#state_var, state_var}
第四步:使用示例
现在你可以这样初始化状态机,完全不用手动写字符串名称:
int main() { // 定义各个状态的Param对象 Param state1{1.5f, 4, 'c'}; Param state2{3.2f, 7, 'x'}; Param state3{0.8f, 2, 'a'}; // 初始化状态机,宏自动绑定变量名和Param StateMachine sm({ BIND_STATE(state1), BIND_STATE(state2), BIND_STATE(state3) }); // 通过名称直接访问对应的Param auto& my_state = sm.get_state("state1"); my_state.float_val = 2.0f; // 修改状态数据 }
额外优化建议
如果你追求更高的类型安全(避免拼写错误的字符串),可以考虑结合C11的enum class或者C20的constexpr字符串做编译期检查,但上面的方案已经能很好满足通用状态机的需求,而且兼容性更强。
这个方案的核心是把"名称标识"从Param内部转移到StateMachine的映射表中,通过宏减少重复工作,同时保持初始化的简洁性。
内容的提问来源于stack exchange,提问作者Reavegen
相关产品推荐
相关产品推荐

