Boost type_index库的实现细节

Boost type_index库的实现细节

前面,有一章节,介绍了boost type_index库中的基本使用方式,这章来介绍boost type_index库的具体的实现细节。

简单回顾一下boost type_index库的功能。主要有如下功能:

  • 使用typeindex::type_id来获取某种静态类型不带cvr修饰的类型信息,比如:typeindex::type_id().pretty_name(),他返回的是int,而不是const int
  • 使用typeindex::type_id_with_cvr来获取某种某种静态类型信息。比如:typeindex::type_id().pretty_name(),他返回的是int const。
  • 使用typeindex::type_id_runtime(const T &t)来,获取t的运行时类型信息。
  • 我们可以通过上面描述的个模板函数来创建type_index实例,我们可以调用type_index类型实例的一些方法来获取类型的一些相关名称。比如:
    • 调用type_index::raw_name()来获取编译器了解的类型名称
    • 调用type_index::pretty_name()来获取用户可以阅读的名称
    • 调用type_index::name()来获取类型名称。(其实,从实现角度上来讲,这个方法,可能有些多余)

接下来会介绍boost type_index库的具体的实现细节。

下面的三个模板函数和type_index类型定义都是位于:boost/type_index.hpp文件中

type_id模板函数的实现

template <typename T>
type_index type_id()
{
    return type_index::type_id<T>();
}

其实他就是一个辅助方法,他内部是直接调用type_index自身的type_id方法来产生type_index实例的。关于type_index类型,后面的相关章节。

type_id_with_cvr模板函数的实现

template <typename T>
type_index type_id_with_cvr()
{
    return type_index::type_id_with_cvr<T>();
}

他就是一个辅助方法,他内部是直接调用type_index自身的type_id_with_cvr方法来产生type_index实例的。关于type_index类型,后面的相关章节。

type_id_runtime模板函数的实现

template <typename T>
type_index type_id_runtime(const T &t)
{
    return type_index::type_id_runtime(t);
}

他就是一个辅助方法,他内部是直接调用type_index自身的type_id_runtime方法来产生type_index实例的。关于type_index类型,后面的相关章节。

type_index类型

他是一个typedef定义的类型。具体的定义部分,参看下面的代码:

//其实这儿还有用户自己实现type_index库的情况,这种情况,我们不进行讨论,我们只看boost的自带的实现方式
...
#elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
    typedef boost::typeindex::stl_type_index type_index;
#else 
    typedef boost::typeindex::ctti_type_index type_index;
#endif

从上面的条件宏语句中,我们可以很容易看出:

如果当前编译器vc+,或者当rtti开启的时候,type_index实际上是boost::typeindex::stl_type_index的别名。至于为什么会这样来设置,请看后面的stl_type_index实现部分。

如果当前编译器,不是vc++,并且rtti被禁用的时候或者BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY被定义的时候,type_index实际上是boost::typeindex::ctti_type_index的别名

下面会介绍boost::typeindex::stl_type_index和boost::typeindex::ctti_type_index的详细细节。

这面所描述的两个类所在的hpp文件,他是有选择的被包含在boost/type_index.hpp中文件中的。详细代码请看:

// 这儿是用户自己实现type_index库的情况,我们不进行讨论
#if defined(BOOST_TYPE_INDEX_USER_TYPEINDEX)
#   include BOOST_TYPE_INDEX_USER_TYPEINDEX
#   ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
#       pragma detect_mismatch( "boost__type_index__abi", "user defined type_index class is used: " BOOST_STRINGIZE(BOOST_TYPE_INDEX_USER_TYPEINDEX))
#   endif
// 这儿是rtti被禁用,或者是vc++编译器的情况
#elif (!defined(BOOST_NO_RTTI) && !defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)) || defined(BOOST_MSVC)
//下面包含的hpp文件,就是boost::typeindex::stl_type_index的声明和实现部分
#   include <boost/type_index/stl_type_index.hpp>
// 当前编译器为vc++编译器,并且rtti被关闭的时候
#   if defined(BOOST_NO_RTTI) || defined(BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY)
// 内部定义了BOOST_TYPE_INDEX_REGISTER_CLASS宏,这个宏仅的实现细节,请参照后面章节
#       include <boost/type_index/detail/stl_register_class.hpp>
#       ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
#           pragma detect_mismatch( "boost__type_index__abi", "RTTI is off - typeid() is used only for templates")
#       endif
#   else
#       ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
#           pragma detect_mismatch( "boost__type_index__abi", "RTTI is used")
#       endif
#   endif

#else
// 这儿就是当前编译器不是vc++编译器,并且rtti被禁用的情况,或者BOOST_TYPE_INDEX_FORCE_NO_RTTI_COMPATIBILITY被定义的时候禁止此分支

// 下面的头文件是boost::typeindex::ctti_type_index类型定义的地方
#   include <boost/type_index/ctti_type_index.hpp>

// 他是boost::typeindex::ctti_type_index对应的BOOST_TYPE_INDEX_REGISTER_CLASS宏的定义部分
#   include <boost/type_index/detail/ctti_register_class.hpp>
#   ifdef BOOST_HAS_PRAGMA_DETECT_MISMATCH
#       pragma detect_mismatch( "boost__type_index__abi", "RTTI is off - using CTTI")
#   endif
#endif

从上面代码可以看出,stl_type_index类的定义部分位于:boost/type_index/stl_type_index.hpp中,ctti_type_index类的定义部分位于:boost/type_index/ctti_type_index.hpp中。

type_index_facade

这个类是下面所要介绍的stl_type_index和ctti_type_index的门面类。他实现门面的方式是通过使用模板作为上面两个类的积累形式。

类简单原型如下:

// Derived 是派生类类型
// TypeInfo 是派生类内部保存类型信息的类
template <class Derived, class TypeInfo>
class type_index_facade
{
public:
    typedef TypeInfo type_info_t;

    // 内部直接调用子类的方法
    // 这儿就是利用模板实现的静态多态,这种技术在微软的wtl库中被大量使用   
    const char *name() const BOOST_NOEXCEPT
    {
        return derived().raw_name();
    }

    // 这儿调用的是派生类的name方法,他的两个子类都会重新定义pretty_name方法的
    string pretty_name() const BOOST_NOEXCEPT
    {
        return derived().name();
    }

    //直接比较的是类型名称
    bool equal(const Derived &rhs) const BOOST_NOEXCEPT
    {
        const char *left = derived().raw_name();
        const char *right = rhs.raw_name();

        return (left == right) || (0 == strcmp(left, right));
    }

    bool before(const Derived &rhs) const BOOST_NOEXCEPT
    {
        const char *left = derived().raw_name();
        const char *right = rhs.raw_name();

        return (left != right) || (strcmp(left, right) < 0);    
    }

    // 获取hash值,注意内部实现依赖于,一个提前声明的模板方法
    // hash_range,所以在实际使用这个hash_code方法的时候,必须要包含boost/functional/hash.hpp,或者实现自己的template<typename Iter> std::size_t hash_range(Iter begin, Iter end)。否则程序链接阶段会出现未定义问题。
    std::size_t hash_code() const BOOST_NOEXCEPT
    {
        return hash_range(derived().name(), derived().name() + strlen(name()));
    }
    ...
private:
    const Derived& derived() const BOOST_NOEXCEPT
    {
        return *static_cast<const Derived*>(this);
    }
};

从上面可以看到,他只提供以下几种类型方法:

  1. name方法,pretty_name方法
  2. before方法,equal方法
  3. hash_code方法

其实他提供的三类方法,本质上将只是为派生类提供,比较功能,输出流功能和获取hash值功能,具体实现看下面代码:

template <class Derived, class TypeInfo>
inline bool operator==(const type_index_facade<Derived, TypeInfo> &lhs, const type_index_facade<Derived, TypeInfo> &rhs) BOOST_NOEXCEPT
{
    // 将派生类类型传进来,这儿进行的static_cast就是静态转换
    // 对于对于上面描述的两个类型:stl_type_index和ctti_type_index来讲,他们最终调用的是派生类的raw_name方法
    return static_cast<const Derived&>(lhs).equal(static_cast<const Derived&>(rhs));
}

template <class Derived, class TypeInfo>
inline bool operator<(const type_index_facade<Derived, TypeInfo> &lhs, const type_index_facade<Derived, TypeInfo> &rhs) BOOST_NOEXCEPT
{
    return static_cast<const Derived&>(lhs).before(static_cast<const Derived&>(rhs));
}

// 下面还要重载剩余的4从关系运算符,其实实现原理和stl 的utility库中的那个重载关系符实现原理是一样的,比如:
template <class Derived, class TypeInfo>
inline bool operator!=(const type_index_facade<Derived, TypeInfo> &lhs, const type_index_facade<Derived, TypeInfo> &rhs) BOOST_NOEXCEPT
{
    return !(lhs == rhs);
}

template <class Derived, class TypeInfo>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值