C++ 不使用继承如何动态修改类内typedef适配Eigen矩阵类型
核心问题解答
首先明确你提出的几个疑问:
- typedef 属于C++静态类型系统的语法,确实是编译期完全确定的,运行时没有任何手段可以动态修改其绑定的类型。
- Eigen 矩阵的标量类型不能指定为
auto实现适配:auto仅用于编译期类型推导,最终推导完成后还是固定的编译期类型,无法满足运行时动态切换的需求。
低改造成本解决方案
不需要派生新类,根据你的实际场景二选一即可:
方案1:运行时动态切换(支持同一进程根据启动参数选类型)
用 std::variant 包装两种矩阵类型,仅修改 DataStorage 类内部实现,外部调用完全不用改动:
- 替换原有
eType定义:
#include <variant> using eType = std::variant< Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic>, Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> >;
- 在
DataStorage类中新增构造参数,根据启动时传入的参数初始化对应类型的eType实例。 - 原有类内的读写接口内部用
std::visit做类型分发,对外接口签名完全保留,不影响任何外部调用:
// 原有读接口签名不变,外部调用无感知 unsigned char getVal(int row, int col) const { return std::visit([&](const auto& mat) -> unsigned char { // 可根据需求自定义类型转换逻辑,不需要转换直接返回也可以 return static_cast<unsigned char>(mat(row, col)); }, m_storage_mat); } // 若需要新增float类型读写接口直接加即可,不影响原有逻辑 float getValFloat(int row, int col) const { return std::visit([&](const auto& mat) -> float { return static_cast<float>(mat(row, col)); }, m_storage_mat); }
方案2:编译期切换(仅需要两种独立编译版本的场景)
如果不需要同一进程同时支持两种类型,只是需要根据配置编译不同版本,改造成本几乎为零:
- 将
DataStorage改为模板类,标量类型作为模板参数:
template<typename Scalar> class DataStorage { public: typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> eType; // 原有类的所有实现直接复用,把用到unsigned char的地方替换为Scalar即可 };
- 全局新增类型别名,通过编译宏切换:
#ifdef ENABLE_FLOAT_STORAGE using DataStorageInst = DataStorage<float>; #else using DataStorageInst = DataStorage<unsigned char>; #endif
- 全局批量替换代码中所有的
DataStorage类型为DataStorageInst,编译时添加-DENABLE_FLOAT_STORAGE参数即可生成float版本,不加则沿用原unsigned char版本,运行时零额外开销。
内容的提问来源于stack exchange,提问作者Emilio7773
相关产品推荐
相关产品推荐

