您的位置:首页 > 其它

boost.any源码整理和使用说明

2007-08-24 22:44 459 查看

Source

#include <algorithm>
#include <typeinfo>

#include "boost/config.hpp"
#include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/is_reference.hpp>
#include <boost/throw_exception.hpp>
#include <boost/static_assert.hpp>

namespace kimi_boost
{
class any
{
template<typename ValueType>
friend ValueType * any_cast(any *);
public:
//ctor
any() : content(0){}
//ctor: from a value of any type
template<typename ValueType>
any(const ValueType & value): content(new holder<ValueType>(value)){}
//copy-ctor: from another any object
any(const any & other): content(other.content ? other.content->clone() : 0){}
//dtor
~any(){delete content;}

//swap two any objects
any& swap(any & rhs)
{
std::swap(content, rhs.content);
return *this;
}

//assign from a value of any type
template<typename ValueType>
any & operator=(const ValueType & rhs)
{
any(rhs).swap(*this);
return *this;
}

//assign from another any object
any & operator=(const any & rhs)
{
any(rhs).swap(*this);
return *this;
}

bool empty() const {return !content;}

//get the type_info& using RTTI
const std::type_info & type() const
{
//see holder::type()
return content ? content->type() : typeid(void);
}

private:
//inner class
class placeholder
{
public:
virtual ~placeholder(){}
virtual const std::type_info & type() const = 0;
virtual placeholder * clone() const = 0;
};//class placeholder

template<typename ValueType>
class holder : public placeholder
{
public:
holder(const ValueType & value): held(value){}

virtual const std::type_info & type() const
{return typeid(ValueType);}

//note the return type is "placeholder*" rather than "holder*"
virtual placeholder * clone() const
{return new holder(held);}

//the real object of various type
ValueType held;
};//class holder

private://the only member data
placeholder* content;
};//class any

//an exception class that will be thrown when type cast fails
class bad_any_cast : public std::bad_cast
{
public:
virtual const char * what() const throw()
{return "boost::bad_any_cast: failed conversion using boost::any_cast";}
};

//两个指针版本的any_cast不会抛出异常,失败时返回
//any_cast functions are based on typeid and type_info

template<typename ValueType>
ValueType * any_cast(any * operand)
{
return ( operand && operand->type() == typeid(ValueType) )
? &static_cast<any::holder<ValueType> *>(operand->content)->held
: 0;
}

template<typename ValueType>
const ValueType * any_cast(const any * operand)
{
return any_cast<ValueType>(const_cast<any *>(operand));
}

//两个引用版本的any_cast失败时会抛出异常
template<typename ValueType>
ValueType any_cast(const any & operand)
{
typedef typename remove_reference<ValueType>::type nonref;

const nonref * result = any_cast<nonref>(&operand);
if(!result)
boost::throw_exception(bad_any_cast());
return *result;
}

template<typename ValueType>
ValueType any_cast(any & operand)
{
typedef typename remove_reference<ValueType>::type nonref;

nonref * result = any_cast<nonref>(&operand);
if(!result)
boost::throw_exception(bad_any_cast());
return *result;
}

}

Test code

bool is_empty(const kimi_boost::any & operand)
{
return operand.empty();
}

bool is_int(const kimi_boost::any & operand)
{
return operand.type() == typeid(int);
}

bool is_char_ptr(const kimi_boost::any & operand)
{
try
{
kimi_boost::any_cast<const char *>(operand);
return true;
}
catch(const kimi_boost::bad_any_cast &)
{
return false;
}
}

bool is_string(const kimi_boost::any & operand)
{
return kimi_boost::any_cast<std::string>(&operand);
}

void count_all(std::list<kimi_boost::any> & values, std::ostream & out)
{
out << "#empty == "
<< std::count_if(values.begin(), values.end(), is_empty) << std::endl;
out << "#int == "
<< std::count_if(values.begin(), values.end(), is_int) << std::endl;
out << "#const char * == "
<< std::count_if(values.begin(), values.end(), is_char_ptr) << std::endl;
out << "#string == "
<< std::count_if(values.begin(), values.end(), is_string) << std::endl;
}

void any_test()
{
std::list<kimi_boost::any> la;
la.push_back(int(1));
la.push_back(double(1));
la.push_back(char(1));
la.push_back(float(1));
la.push_back(kimi_boost::any((char)3));//char type
la.push_back(kimi_boost::any((int)3));//int type
la.push_back(kimi_boost::any());//empty
la.push_back(kimi_boost::any());//empty

count_all(la,std::cout);

}

Output

#empty == 2
#int == 2
#const char * == 0
#string == 0
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: