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);
}
};
从上面可以看到,他只提供以下几种类型方法:
- name方法,pretty_name方法
- before方法,equal方法
- 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>