荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: Version (Who makes history and why), 信区: Program
标  题:  boost::any实现分析
发信站: 荔园晨风BBS站 (Tue Mar 25 18:49:42 2003), 站内信件

boost::any实现分析

看了boost::any的源码受到启发,写点心得。:)

    boost::any并不是一个类模板,而仅是一个普通类。但它的成员函数type()却
可以在运行时返回不同的类型信息(type_info)。这种功能的实现依靠了两种技
术:
(1)成员函数/构造函数模板
(2)继承自普通类的类模板
    以下讨论boost::any如何运用这两种技术来实现其功能。

    首先,boost::any有一个构造函数模板:

    template<typename ValueType>
    any(const ValueType & value);

    用于在初始时刻由其参数,通过编译器的类型推断来获得value的类型信息。
value必须保存下来提供给any_cast使用,而value的类型信息ValueType也必须以
某种形式保存下来供成员函数type()使用。但是由于boost::any并不是一个类模板
,所以它不能有一个ValueType或者SomeClass<ValueType>这样依赖于ValueType的
成员变量,也就是说,由于boost::any是一个普通类,所以它的成员变量必须有一
个不依赖于ValueType的预先确定的类型。
    如果我们使用void*类型来存放value,就会丢掉类型信息。试图使用
type_info型的变量来保存类型信息是行不通的。(看一下type_info的声明就会知
道,它的copy constructor, operator=以及operator&都是私有的。)也就是说,
我们必须使用一个确定类型的成员变量来保存不确定的类型信息。为此,把虚函数
和类模板结合起来。在boost::any中使用的方法就是,用一个虚基类指针
placeholder*作为成员变量的类型,该类拥有一个纯虚函数type():

    virtual const std::type_info & type() const = 0;

    placeholder必须是一个确定类型的类,但它的派生类却可以是模板类,其中
可以使用ValueType的相关类型来保存value,同时也不丢失其类型信息,而且可通
过虚函数type()来重新获得该类型信息:

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

        ...

    public: // representation

        ValueType held;

    };

    同时,在any类的构造函数模板中将new holder<ValueType>(value)赋予它的
成员变量content(类型为placeholder*)。
    以后,在any::type()中通过调用虚函数holder<ValueType>::type()来获得该
类型信息:

    const std::type_info & type() const
    {
        return content ? content->type() : typeid(void);
    }

    在any_cast函数中,则通过boost::type()来保证类型安全。以指针类型的
any_cast为例:

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

附:boost::any的代码(去掉了预处理宏和namespace boost{}修饰):
class any
{
public: // structors

    any()
      : 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)
    {
    }

    ~any()
    {
        delete content;
    }

public: // modifiers

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

    template<typename ValueType>
    any & operator=(const ValueType & rhs)
    {
        any(rhs).swap(*this);
        return *this;
    }

    any & operator=(const any & rhs)
    {
        any(rhs).swap(*this);
        return *this;
    }

public: // queries

    bool empty() const
    {
        return !content;
    }

    const std::type_info & type() const
    {
        return content ? content->type() : typeid(void);
    }

private: // types

    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: // representation

    template<typename ValueType>
    friend ValueType * any_cast(any *);

    placeholder * content;

};

/////////////////////////////////////////////////////////////////////
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";
    }
};

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>
                : 0;
}

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

template<typename ValueType>
ValueType any_cast(const any & operand)
{
    const ValueType * result = any_cast<ValueType>(&operand);
    if(!result)
        throw bad_any_cast();

    return *result;
}

--
                      *
          *                                  *
                          *             *
                      no more to say
                  ★     just wish you   ★
                            good luck

※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.1.50]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店