万能数据类型boost::any杂谈
1、boost::any 与 _variant_t
刚接触boost::any时,不禁让人想起了MS的_variant_t类,因为两者都可以存放其他的类型的值。
比较一下两者可以发现:_variant_t只能容纳 VARIANT 数据类型(详见MSDN),而boost::any可以容纳用
户自定义数据类型,如结构体,类等,这由两者的实现方法不同造成的:
_variant_t利用的是重载机制,即_variant_t中重载了若干个拷贝构造函数和赋值函数(看起来有点恐怖)
,从而实现了ARIANT 数据类型能够向_variant_t类型转换。正是如此限制了其与其它数据类型间的转换。
boost::any则充分利用了模板机制,只需一个模板拷贝构造函数和模板赋值函数就实现了各种数据类型向
boost::any的转换,省去了重载之苦,甚是妙哉!
2、boost::any 与 CBCGPProp
boost::any的帮助文档中提到它的一个应用,可以用来构建属性,如下:
struct property
{
property();
property(const std::string &, const boost::any &);
std::string name;
boost::any value;
};
typedef std::list<property> properties;
这令我想起在BCG中有一个属性类CBCGPProp。CBCGPProp提供了有关属性的管理(详见BCGP源代码),其内部使
用的是_variant_t接收各中 VARIANT 数据类型。
根据struct property,我写了一个小小的测试程序,详见附录。
3、boost::any之使用
boost::any的结构十分简单,只有几个成员函数。
1)给boost::any赋值
某个数据类型要赋值给boost::any,需要满足三个条件:
*A ValueType is CopyConstructible .
*A ValueType is optionally Assignable.
*The destructor for a ValueType upholds the no-throw exception-safety guarantee.
eg:
int i = 100;
boost::any anyInt= i;
boost::any anyDouble(200.0);
注:把字符串赋给boost::any时需要借助std::string
boost::any anyStr;
//anyStr = "Haha"; //wrong! "Haha"会被看成是char[]
anyStr = std::string("Haha"); //right
2)把boost::any的值赋给某个变量
这需要借助boost::any_cast模板函数。当转换失败是会抛出bad_any_cast异常。
//bad_any_cast
boost::any anyDouble(200.5);
float fValue = 0.0;
try{
fValue = boost::any_cast<float>(anyDouble);
}
catch(boost::bad_any_cast& e){
std::cout << e.what() <<std::endl;
}
-----------------------------------------------------------------------
附录:
#include <boost/any.hpp>
#include <string>
#include <iostream>
#include <list>
#include <iomanip>
struct property
{
property(){};
property(const std::string & name,
const boost::any & value)
{
m_name = name;
m_value = value;
};
std::string m_name;
boost::any m_value;
};
typedef std::list<property*> properties;
void OutPutProperty(properties props)
{
property* pProp = 0;
boost::any anyValue;
for(properties::iterator it = props.begin();
it != props.end(); ++it)
{
pProp = *it;
anyValue = pProp->m_value;
if(!anyValue.empty())
{
const std::type_info& info = anyValue.type();
//std::cout << info.name();
std::cout << std::setiosflags(std::ios::left)
<< std::setw(10)
<< pProp->m_name << "------ ";
if(info == typeid(int))
std::cout << boost::any_cast<int>(anyValue)
<<std::endl;
else if(info == typeid(double))
std::cout << boost::any_cast<double>(anyValue)
<<std::endl;
else if(info == typeid(std::string))
std::cout << boost::any_cast<std::string>(anyValue)
<<std::endl;
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
properties person;
person.push_back(new property("Name", std::string("Mythma")));
person.push_back(new property("Sex", std::string("Male")));
person.push_back(new property("Age", 25));
person.push_back(new property("Salary", 500.50));
//输出
OutPutProperty(person);
//释放内存
for(properties::iterator it = person.begin();
it != person.end(); ++it)
{
delete *it;
*it = 0;
}
person.clear();
//把自定义类型赋值给boost::any
boost::any anyClass;
property prop;
anyClass = prop;
const std::type_info& info = anyClass.type();
std::cout << info.name();
//字符串
boost::any anyStr;
//anyStr = "Haha"; //wrong
anyStr = std::string("Haha");
const std::type_info& infoStr = anyStr.type();
std::cout << infoStr.name();
return 0;
}