【C++11】Any类的实现

boost库有一个Any类,是一个特殊的只能容纳一个元素的容器,他可以擦除类型,给任何类型赋值。

boost::any a = 1;
boost::any a = 1.1;

std::vector<boost::any> v;
v.push_back(a);
v.push_back(b);

int va = boost::any_cast<int>(a);
...

关键点就是,需要擦除具体的类型,使用一种通用的方式保存所有的类型的数据,这里可以使用继承的方式实现,具体如下:

实现

class Any
{
public:
    Any() : m_tpIndex(std::type_index(typeid(void))) {}
    Any(Any& other) : m_ptr(other.clone()), m_tpIndex(other.m_tpIndex) {}
    Any(Any&& other) : m_ptr(std::move(other.m_ptr)), m_tpIndex(std::move(other.m_tpIndex)) {}

    //判断U是 Any类型还是模板类型
    template<typename U, 
        class = typename std::enable_if<!std::is_same<typename std::decay<U>::type, Any>::value, U>::type>
    Any(U&& value)
        : m_ptr(new Derived<typename std::decay<U>::type>(std::forward<U>(value)))
        , m_tpIndex(typeid(typename std::decay<U>::type)) {}

    //判空
    bool isNull()
    {
        return !bool(m_ptr);
    }

    //判断类型
    template<typename T>
    bool is()
    {
        return m_tpIndex == type_index(typeid(T));
    }

    //Any类 转换成具体的类
    template<typename T>
    T& cast()
    {
        if (!is<T>())
        {
            cout << "can not cast " << typeid(T).name() << " to "
                << m_tpIndex.name() << endl;
            throw bad_cast();
        }
        auto derived = dynamic_cast<Derived<T>*>(m_ptr.get());
        return derived->m_value;
    }

    Any& operator=(const Any& other)
    {
        if (m_ptr == other.m_ptr)
        {
            return *this;
        }
        m_ptr = other.clone();
        m_tpIndex = other.m_tpIndex;
        return *this;
    }

private:
    struct Base;
    using BasePtr = std::unique_ptr<Base>;

    //基类非模板用了擦除具体类型
    struct Base
    {
        virtual BasePtr clone() const = 0;
    }; 

    //子类存放具体内容
    template<typename T>
    struct Derived : public Base
    {
        template<typename...Args>
        Derived(Args&& ...args) : m_value(std::forward<Args>(args)...){}
        BasePtr clone() const
        {
            return BasePtr(new Derived(m_value));
        }

        T   m_value;
    };

    //构造函数使用 clone
    BasePtr clone() const
    {
        if (m_ptr != nullptr)
        {
            return m_ptr->clone();
        }
        return nullptr;
    }

    BasePtr         m_ptr;      //记录实际值
    std::type_index m_tpIndex;  //记录值对应的内容
};

void testAny()
{
    Any a = 1;
    Any b = string("hello,world");
    Any c;

    cout << std::boolalpha;
    cout << "a is null:" << a.isNull() << endl;
    cout << "b is null:" << b.isNull() << endl;
    cout << "c is null:" << c.isNull() << endl;

    cout << endl;

    cout << "a is int:" << a.is<int>() << endl;
    cout << "a is string:" << a.is<string>() << endl;
    cout << "a is void:" << a.is<void>() << endl;

    cout << endl;

    cout << "a = " << a.cast<int>() << endl;
    cout << "b = " << b.cast<string>() << endl;
    //cout << "c = " << c.cast<void>() << endl;

    cout << endl;
    //error
    cout << "a = " << a.cast<string>() << endl;

    vector<Any> v;
    v.push_back(1);
    v.push_back(1.2);
    v.push_back(string("str"));

    cout << v[1].cast<double>() << endl;
}

打印结果如下:
这里写图片描述

如果cast转换失败则会发生如下异常:
这里写图片描述

猜你喜欢

转载自blog.csdn.net/gx864102252/article/details/79560686