待解决的问题
- 当同一个 X( 变量/返回值/参数) 需要在接纳不同类型的数据的时候。
Any a ;
a = 1 ;
// ... do something with a
a = "1";
// ... do something with a
- 当不同类型(不来自同一个继承体系)的对象需要被视为统一类型的时候。(比如放入同一个容器)
std::array<Any,2> data;
data[0]=1;
data[1]="1";
传统的解决方案
void *
传统解决方案的不足
- 丢失类型信息
void * ret = new A() ;
assert(typeid(ret) == (new A())); // assert failed !
- 容易引入内存问题,未定义问题
void * base = new A() ;
B * now = static_cast<B*>(base); // undefined behavior ...
实现Any需要解决的问题
1. 如何在不丢失类型的情况下任意存储数据
2. 如何安全的,动态的 [ 设置/删/改/查 ] 数据
Boost.Any 源码解析
boost 版本号 :1.54
我对代码顺序进行了简单的调整, 删除了和核心无关的支持c++11的右值接口和friend
关键字相关代码。
1. 如何在不丢失类型的情况下任意存储数据
// 存储抽象接口,支持返回类型和克隆自身.
// void * 的替代品 --> placeholder *
class placeholder
{
public: // structors
virtual ~placeholder()
{
}
public: // queries
virtual const std::type_info & type() const = 0;
virtual placeholder * clone() const = 0;
};
// 存储核心模板类.
template<typename ValueType>
class holder : public placeholder
{
public: // structors
holder(const ValueType & value)
: held(value)
{
}
public: // queries
virtual const std::type_info & type() const
{ // 直接返回自身的类型
return typeid(ValueType);
}
// 利用拷贝构造获得副本
virtual placeholder * clone() const
{
return new holder(held);
}
public: // representation
// 任意类型的数据所具体实现的类均使用自己本来的类型保存,不会丢失类型信息。
ValueType held;
private: // intentionally left unimplemented
holder & operator=(const holder &);
};
2. 如何安全的,动态的 [ 设置/删/改/查 ] 数据
// 代码顺序略有调整
class any
{
public:
placeholder * content; // 指向实际存储数据
public: // structors
// 一系列构造函数 ...
any() BOOST_NOEXCEPT
: content(0)
{
}
template<typename ValueType>
any(const ValueType & value)
: content(new holder<ValueType>(value))
{
}
any(const any & other)
: content(other.content ? other.content->clone() : 0)
{
}
// 析构函数 , delete 0 真的好么 ?
~any() BOOST_NOEXCEPT
{
delete content;
}
public: // modifiers
// swap 接口,直接互换数据内存.
any & swap(any & rhs) BOOST_NOEXCEPT
{
std::swap(content, rhs.content);
return *this;
}
// = 运算符
// 由于any 可以由任意类型参数默认构造 , 所以这个接口进化为 Any a = 任意对象。
any & operator=(const any& rhs)
{
any(rhs).swap(*this);
return *this;
}
public: // queries
// 是否被设置过。
bool empty() const BOOST_NOEXCEPT
{
return !content;
}
// 但前的类型信息.
const std::type_info & type() const
{
return content ? content->type() : typeid(void);
}
};
// 获取存储的数据指针, 注意此时传入的any的指针
template<typename ValueType>
ValueType * any_cast(any * operand) BOOST_NOEXCEPT
{
return operand &&
operand->type() == typeid(ValueType)
? &static_cast<any::holder<ValueType> *>(operand->content)->held
: 0;
}
// 获取const的存储的数据指针,
template<typename ValueType>
inline const ValueType * any_cast(const any * operand) BOOST_NOEXCEPT
{
return any_cast<ValueType>(const_cast<any *>(operand));
}
// 获取一个存储内容的拷贝 , 注意参数是引用
template<typename ValueType>
ValueType any_cast(any & operand)
{
typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
nonref * result = any_cast<nonref>(&operand);
if(!result)
boost::throw_exception(bad_any_cast());
return *result;
}
// const 版本获得拷贝.
template<typename ValueType>
inline ValueType any_cast(const any & operand)
{
typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
return any_cast<const nonref &>(const_cast<any &>(operand));
}