boost::any库是个很短小的类,它的主要作用是定义一个变量来存放任意类型的数据,我们首先来看下boost::any的使用方法。
boost::any最常见的用法
#include <iostream>
#include <list>
#include <boost/any.hpp>
typedef std::list<boost::any> list_any; // 类型定义
void fill_list(list_any& la) {
la.push_back(10); // 存放整数
la.push_back(std::string("glemontree")); // 存放字符串对象,不能是la.push_back("glemontree"),否则会被当做字符串数组
}
void show_list(list_any& la) {
list_any::iterator it;
boost::any anyone;
for (it = la.begin; it!= la.end(); ++it) {
anyone = *it;
// C++中,typeid用于返回指针或引用所指对象的实际类型,typeid是操作符,不是函数
if (anyone.type() == typeid(int)) {
std::cout << boost::any_cast<int>(*it) << std::endl;
} else if (anyone.type() == typeid(std::string)) {
// c_str()函数返回一个指向正规C字符串的指针,内容与本string相同
std::cout << boost::any_cast<std::string>(*it).c_str() << std::endl;
}
}
}
boost::any可以表示任意类型,因此list_any可以存放任意类型的对象,也正因为boost::any可以表示任意类型,因此用不了多态的特性,因为没有统一的接口,因此在show_list()函数中获取容器中的元素时需要判别元素的真正类型,这增加了程序员的负担。
boost::any源码
实现any的功能主要由三部分组成:
- any类
- 真正保存数据的holder类和其基类placeholder
- 获取真正数据的模板函数any_cast,类型转换的功能
#include <iostream>
#include <list>
#include <cassert>
class any {
public:
class placeholder {
public:
virtual ~placeholder() {
}
public:
virtual const std::type_info& type() const = 0;
virtual placeholder* clone() const = 0;
};
template<typename ValueType>
class holder : public placeholder {
public:
holder(const ValueType& value): held(value) {
}
public:
virtual const std::type_info& type() const {
return typeid(ValueType);
}
virtual placeholder* clone() const {
return new holder(held);
}
public:
ValueType held;
};
public:
any(): content(NULL) {
}
//模板构造函数,参数可以是任意类型,真正的数据保存在content中
template<typename ValueType>
any(const ValueType& value): content(new holder<ValueType>(value)) {
}
//拷贝构造函数
any(const any& other): content(other.content ? other.content->clone() : 0) {
}
~any() {
if (NULL != content) {
delete content;
}
}
private:
placeholder* content;
template<typename ValueType>
friend ValueType any_cast(const any* operand);
public:
const std::type_info& type() const {
return content ? content->type() : typeif(void);
}
};
template<typename ValueType>
ValueType any_cast(const any& operand) {
assert(operand.type() == typeid(ValueType));
return static_cast<any::holder<ValueType>*>(operand.content)->held;
}