如何让继承STL容器的自定义类兼容boost::assign初始化函数?
用boost::assign适配继承STL容器的自定义类(C++03环境)
没问题,我来帮你搞定在C03里用boost::assign给自定义STL派生容器初始化的需求——老项目里没法用C11初始化列表,boost::assign确实是个靠谱的替代方案!
1. 如何将boost::assign用于继承STL容器的自定义容器?
boost::assign的list_of()、map_list_of()本质上会返回一个代理对象,这个对象可以被转换为对应的STL容器,或者提供迭代器供容器插入元素。要让自定义容器能用它,核心是让自定义容器能和这个代理对象交互,主要有两种简单方式:
方式一:给自定义容器添加适配的构造/赋值运算符
因为自定义容器继承了STL容器,我们可以添加模板构造函数或赋值运算符,把代理对象转发给基类处理。举个例子:
#include <vector> #include <boost/assign/list_of.hpp> // 自定义vector容器 class MyVector : public std::vector<int> { public: // C++03里不能用using继承基类构造,手动写默认构造 MyVector() : std::vector<int>() {} // 模板构造函数:接受boost::assign的代理对象,转发给基类构造 template <typename ProxyType> MyVector(const ProxyType& proxy) : std::vector<int>(proxy) {} // 模板赋值运算符:同样转发给基类 template <typename ProxyType> MyVector& operator=(const ProxyType& proxy) { std::vector<int>::operator=(proxy); return *this; } }; // 使用示例 int main() { MyVector nums = boost::assign::list_of(1)(2)(3)(4); // 现在nums里就有1、2、3、4这几个元素了 return 0; }
方式二:用boost::assign的工具函数直接操作容器
如果你不想修改自定义容器的代码,boost::assign还提供了push_back()、insert()这类工具函数,它们会直接调用容器的同名成员方法——只要你的自定义容器继承了STL容器的这些方法,就能直接用:
#include <vector> #include <boost/assign/list_of.hpp> class MyVector : public std::vector<int> {}; // 完全继承,不修改 int main() { MyVector nums; // 用boost::assign::push_back直接往容器里塞元素 boost::assign::push_back(nums)(1)(2)(3)(4); return 0; }
2. 让继承std::vector、std::map等的自定义类适配boost::assign的初始化函数
针对不同类型的STL容器,适配方式略有区别,但核心思路和上面一致:
针对序列容器(std::vector、std::list等)
除了上面的两种方式,还可以直接用operator+=,因为boost::assign的代理对象支持范围迭代,而STL序列容器的operator+=接受范围:
MyVector nums; nums += boost::assign::list_of(1)(2)(3);
只要你的自定义容器没有隐藏基类的operator+=(比如没有自己重载同名方法),这个写法就能直接生效。
针对关联容器(std::map、std::set等)
以std::map为例,用map_list_of()的话,同样可以用构造/赋值转发,或者用boost::assign::insert()工具函数:
方式一:添加构造/赋值运算符
#include <map> #include <boost/assign/list_of.hpp> class MyMap : public std::map<int, std::string> { public: MyMap() : std::map<int, std::string>() {} template <typename ProxyType> MyMap(const ProxyType& proxy) : std::map<int, std::string>(proxy) {} template <typename ProxyType> MyMap& operator=(const ProxyType& proxy) { std::map<int, std::string>::operator=(proxy); return *this; } }; // 使用示例 int main() { MyMap key_values = boost::assign::map_list_of(1, "one")(2, "two")(3, "three"); return 0; }
方式二:用insert工具函数
#include <map> #include <boost/assign/list_of.hpp> class MyMap : public std::map<int, std::string> {}; int main() { MyMap key_values; boost::assign::insert(key_values)(1, "one")(2, "two")(3, "three"); return 0; }
注意事项
- 在C03里,不要忘记手动转发基类的构造函数(因为没法用C11的
using语法),不然默认构造可能会出问题。 - 模板构造/赋值运算符是通用写法,不需要特意指定boost的代理类型,因为STL容器本身就能处理这个代理对象的迭代器范围。
内容的提问来源于stack exchange,提问作者Stefan D.
相关产品推荐
相关产品推荐

