转:

原理

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);

我们需要我们的万能类型有如下的行为:

  1. 对外是一个一般的类,使用者压入参数的时候不应该关心类型
  2. 是一个中间层,具体保存数据的应该是一个模板类(Holder)
  3. 必须要能有方法支持任意类型的输入和输出为任意类型

实现

作为接口类,让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;
    };
  1. type()提供了查询类型的能力
  2. 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);

总结

  1. 代码和boost::any中有一些出入,但是我们的目的是为了研究其实现,就忽略了某些细节
  2. 模板技巧: 模板类原来还可以这么用---声明非模板接口,并用模板类实现, 这样在使用这个接口的时候就能避免宿主类显示声明参数类型
  3. boost::any是整个boost库中最简单的类之一,但是某些代码细节还是非常值得学习和借鉴的。
  4. typeid和type_info 感觉有点像c++中的鸡肋,但是某些时候还是有用的
  5. holder.h

 

Boost源码剖析之:泛型指针类any

相关文章: