使用boost::variant构建异构指针向量时如何正确调用成员函数
问题原因
报错的核心原因是boost::variant本身不是指针类型,无法直接使用->运算符调用其内部存储的指针成员。variant作为类型安全的联合容器,必须先解包拿到内部存储的具体类型值,才能执行对应操作。此外原代码缺少<iostream>头文件,调用std::cout也会触发编译错误。
修复方案:使用boost静态访问者
boost::variant要求通过boost::static_visitor和boost::apply_visitor安全访问内部存储的不同类型值,修复后的完整代码如下:
#include <boost/variant.hpp> #include <vector> #include <iostream> template< typename T> class A { public: A(T val): data(val) {} // 补充构造函数初始化data,方便测试 ~A(){} void write(); private: T data; }; template< typename T> void A<T>::write() { std::cout << data << std::endl; } // 定义访问者类 struct WriteVisitor : public boost::static_visitor<void> { template<typename T> void operator()(A<T>* obj_ptr) const { obj_ptr->write(); } }; int main() { A<int> one(123); A<double> two(3.14); typedef boost::variant<A<int>*, A<double>* > registry; std::vector<registry> v; v.push_back(&one); v.push_back(&two); for(unsigned int i =0; i< v.size(); i++) { boost::apply_visitor(WriteVisitor{}, v[i]); } return 0; }
其他可行实现思路
- 多态基类方案(无第三方依赖,兼容性最好)
给模板类A<T>定义一个包含虚函数write()的抽象基类,向量直接存储基类指针,不需要variant即可实现多态调用,代码更简洁:class BaseA { public: virtual void write() = 0; virtual ~BaseA() = default; }; template<typename T> class A : public BaseA { // 其余实现和原代码一致 }; // main中直接存储BaseA* std::vector<BaseA*> v; v.push_back(&one); v.push_back(&two); for(auto ptr : v) ptr->write(); - C17原生
std::variant方案(无boost依赖)
C17标准已内置variant特性,用法和boost::variant逻辑一致,仅需替换相关接口为标准库实现即可:#include <variant> // 其余代码和boost版本一致,遍历调用改为: std::visit([](auto ptr){ ptr->write(); }, v[i]); - C++17
std::any方案(适合类型完全动态的场景)
如果无法提前枚举所有可能存储的A<T>类型,可以用std::any存储指针,调用前通过any_cast转换后执行操作,灵活度最高但性能略低于前两种方案。
内容的提问来源于stack exchange,提问作者user8458838
相关产品推荐
相关产品推荐

