转:
原理
c++是一个强类型的语言,要实现一个万能类型可以考虑用void*来保存数据,然后用类型转换进行操作,如:
class MyAny{
MyAny(void* input):content_(input){
}
typename T>
static_cast<T*>(content_)}
private:
void* content_;
}
一个明显的缺点就是类型不安全。
显然我们可以用template来改进我们的程序:
typename T>
class MyAny{
MyAny(T input):content_(input){
}
return content_;}
private:
T content_;
}
但是这样我们好像就没有解决问题:vector<myany> 好吧,这里就写不下去了。
为了能写下如下的代码:
items;
.push_bacck(1);
.0);
我们需要我们的万能类型有如下的行为:
- 对外是一个一般的类,使用者压入参数的时候不应该关心类型
- 是一个中间层,具体保存数据的应该是一个模板类(Holder)
- 必须要能有方法支持任意类型的输入和输出为任意类型
实现
作为接口类,让any使用。而holder是一个模板类作为类placeholder的实现者, 这样就避免的any对泛型参数的要求(能自动推到导出来)。
我这里模仿了相关的实现,其代码结构应该是这样的:
Any
{
public:
holder_(nullptr){}
ValueType>
val)
: val)){
}
private:
holder_;
};
IHolder{
}
ValueType>
IHolder{
public:
value_(val){
}
}
public:
value_;
}
其中Holder必须提供两个方法:
mb_interface IHolder{
virtual ~IHolder(){}
0;
0;
};
- type()提供了查询类型的能力
- clone()提供了产生数据的能力
在 Any中, 提供了以下几个个接口:
(){
return !holder_;
}
const {
void);
}
Any& operator=(Any rhs){
return swap(rhs);
}
typename ValueType>
Any& const ValueType& val){
this);
}
判断是否为空,查询类型操作,赋值操作
当然必须还有最重要的any_cast操作,我们看其实现:
typename ValueType>
(Any* val){
typeid(ValueType))
? &0;
}
typename ValueType>
(Any& val){
ValueType* rtn = anyCast<ValueType>(&val);
if (!rtn)boost::throw_exception(badAnyCast());
return *rtn;
}
果然好简单。呵呵~~~
最后添上单元测试,整个代码就完善了:
10);
mb::10.0);
mb::(testInt);
EXPECT_EQ(testInt.empty(), false);
EXPECT_EQ(int>(testInt);
EXPECT_EQ(val, 10);
总结
- 代码和boost::any中有一些出入,但是我们的目的是为了研究其实现,就忽略了某些细节
- 模板技巧: 模板类原来还可以这么用---声明非模板接口,并用模板类实现, 这样在使用这个接口的时候就能避免宿主类显示声明参数类型
- boost::any是整个boost库中最简单的类之一,但是某些代码细节还是非常值得学习和借鉴的。
- typeid和type_info 感觉有点像c++中的鸡肋,但是某些时候还是有用的
- holder.h