boost::any是一种通用类型,可以存放任意值。
问题:通用类型any如何存放任意值?
A: 这里的通用类型类似于脚本语言中的类型。
方案一, union结构体:但union只能存放固定种类的值,没有扩展性。
方案二, void *类型: C++是强类型语言,用void *保存后丢失了类型信息,很难保证类型安全。
方案三, 模板: 模板需要参数化,any<int> = 1; any<double> = 1.0; any<X> = x; 显然这不能满足要求。
方案四, 继承和多态,即boost::any类的实现方法。any类存放一placeholder的指针,
而holder是一继承placeholder的模板,模板是拥有类型信息的,因此可以保证类型安全。
废话少说,直接上原理实现代码的demo。
class any
{
public:
//Representation and basic construction of a generalized union type.
any(): content(0)
{
}
~any()
{
delete content;
}
//获得类型信息
const std::type_info &type_info() const
{
return content ? content->type_info() : typeid(void);
}
//INWARD CONVERSIONS
any(const any &other) : content(other.content ? other.content->clone() : 0)
{
}
template<typename value_type>
any(const value_type &value) : content(new holder<value_type>(value)) //函数模板
{
}
any &swap(any &rhs)
{
std::swap(content, rhs.content);
return *this;
}
any &operator=(const any &rhs)
{
return swap(any(rhs)); //利用拷贝构造函数创建局部变量作为参数传给swap,交换值之后,局部变量自动销毁,而rhs值不变;
}
template<typename value_type>
any &operator=(const value_type &rhs) //函数模板
{
return swap(any(rhs));
}
//OUTWARD CONVERSIONS
operator const void *() const
{
return content;
}
template<typename value_type>
bool copy_to(value_type &value) const
{
const value_type *copyable = to_ptr<value_type>();
if(copyable)
value = *copyable;
return copyable;
}
template<typename value_type>
const value_type *to_ptr() const
{
return type_info() == typeid(value_type)? //判断类型是否相同
&static_cast<holder<value_type> *>(content)->held : 0;
}
private:
class placeholder
{
public:
virtual ~placeholder()
{
}
virtual const std::type_info & type_info() const = 0; //获得类型
virtual placeholder *clone() const = 0; //获得值拷贝
};
template<typename value_type>
class holder : public placeholder
{
public:
holder(const value_type &value) : held(value)
{
}
virtual const std::type_info &type_info() const
{
return typeid(value_type);
}
virtual placeholder *clone() const
{
return new holder(held);
}
const value_type held;//存储值
};
placeholder *content;
};
template<typename value_type>
value_type any_cast(const any &operand)
{
const value_type *result = operand.to_ptr<value_type>();
//return result ? *result : throw std::bad_cast(); //有异常,原因未知,将来再分析
if (result)
return *result;
throw std::bad_cast();
}
int main(int argc, char* argv[])
{
any i_a = 3;
int i_b = any_cast<int>(i_a);
std::cout<<i_a<<"\t"<<i_b<<std::endl;
any s_a = std::string("demo");
std::string s_b = any_cast<std::string>(s_a);
std::cout<<s_a<<"\t"<<s_b<<std::endl;
return 0;
}
参考文献:
1, http://www.two-sdg.demon.co.uk/curbralan/papers/ValuedConversions.pdf
2, http://stlchina.huhoo.net/twiki/bin/view.pl/Main/BoostSource_any