Boost type_index库使用介绍
来源:互联网 发布:加工中心g76镗孔编程 编辑:程序博客网 时间:2024/06/06 12:40
Boost type_index库使用介绍
Boost type_index可以获取某种类型的具体类型名称,不管是静态类型名称,还是带有cvr(const-volatile-reference)修饰的名称,还可以获取某个对象运行时的名称。
并且Boost type_index的实现消耗也是非常非常小的,如果编译器启用了rtti特性,那么他内部就实现type_info来辅助实现type_index。如果编译器没有启用rtti特性,那么他就自己实现type_index特性,利用模板+编译器的获取函数具体原型的相关宏(比如__PRETTY_FUNCTION__
(GNU编译器))+一个固定名称的虚函数,就可以实现type_index的所要求的功能了。他的实现肯定小于编译器内部的rtti特性所产生的消耗。
下面会介绍一些这个库的组件和功能。
type_index类型
简单描述:
type_index类型主要就是用来存储某种类型的类型信息,关键信息就是类型的名称相关信息。
type_index的类型声明位于boost/type_index.hpp中,他是一个typedef定义的类型。
当编译器启用rtti特性,或者当前编译器为vc++编译器,那么type_index实际上就是stl_type_index类型。
当编译器关闭了rtti特性,并且当前编译器不是vc++编译器的话,那么type_index实际上就是ctti_type_index类型。
主要方法:
//下面这个类是不存在,主要是为了说明type_index实际类型的主要的方法//再次说明这个类是不存在的class type_index{public: // 下面的三个方法,一般是用户来使用的,一般直接使用pretty_name即可 inline const char* raw_name() const BOOST_NOEXCEPT; inline const char* name() const BOOST_NOEXCEPT; inline const string pretty_name() const BOOST_NOEXCEPT; // 获取此type_index实例的hash_code inline std::size_t hash_code() const BOOST_NOEXCEPT; // 下面三个方法是三个工厂方法,他们一般是通过全局模板方法来调用的 // 用户不用直接来调用它 template <typename T> static type_index type_id() BOOST_NOEXCEPT; template <typename T> static type_index type_id_with_cvr() BOOST_NOEXCEPT; template <typename T> static type_index type_id_runtime() BOOST_NOEXCEPT; // 支持流运算符 // 支持关系运算符};
inline const char* raw_name() const BOOST_NOEXCEPT
本意是用来返回原始的编译器能够认识的类型名称。- 当编译器是vc++编译器的时候,不管rtti是否开启,这个方法生成vc++编译器能够认识的名称,比如:
typeindex::type_id<int>()::raw_name()
返回:.H
… … - 当编译器不是vc++编译器时候,当rtti开启的时候,这个方法返回类型的编译器能够识别的名称,比如:对于mingw来讲
typeindex::type_id<int>()::raw_name()
返回i … …。 - 当编译器不是vc++编译器,并且rtti禁用的时候,这个方法返回的是原始类型名称,这个这个名称后面后多一些其他多余字符,比如对于mingw编译器来讲,
typeindex::type_id<int>()::raw_name()
返回’int]’,其中’]’是多余字符。
- 当编译器是vc++编译器的时候,不管rtti是否开启,这个方法生成vc++编译器能够认识的名称,比如:
inline const string pretty_name() const
用来输出类型的可读名称,当然他的输出内容还是和编译器和rtti的状态有关。- 如果使用vc++编译器,如果是typedef定义类型,他会typedef定义的类型所输出类型所参考的类型, 比如:
typeindex::type_id<string>::pretty_name()
输出为:class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >
。对于基本类型他会输出基本类型。 - 对于mingw编译器,比如mingw有这样输出方式:如果要输出的类型名称是typedef定义的,他会输出typedef定义的类型名称,比如:
typeindex::type_id<string>().pretty_name()
,输出为:std::string
,并且输出某种模板类型的话,他输出的类型名称前面也没有class
字符串(相比于vc++来讲),比如:typeindex::type_id<vector<int> >().pretty_name()
输出为:std::vector<int, std::allocator<int> >
。 - 因为我只有两种编译器来测试,其他编译器情况应该也不一样。但是从实现上来讲,type_index只有两种实现,一种ctti_type_index和stl_type_index,因为对于vc++编译器来讲,不管rtti状态,他总是采用stl_type_index,而对于非vc++编译器来讲,他的type_index具体就依赖于rtti的状态了。如果开启rtti,则type_index总是stl_type_index类型,否则就是ctti_type_index类型。所以我列举了一种vc++编译器类型和一种非vc++编译器类型(mingw)。对于其他非vc++编译器类型,自己可以测试测试。
- 如果使用vc++编译器,如果是typedef定义类型,他会typedef定义的类型所输出类型所参考的类型, 比如:
- inline const char* name() const BOOST_NOEXCEPT;
还是和编译器类型和rtti状态有关。- 对于vc++编译器,不论rtti的状态如何,他输出的都是人能够直接阅读的类型,即和调用pretty_name()方法行为完全相同。
- 对于非vc++来讲,不论rtti的状态如何,他的行为都和raw_name()的行为完全相同。
- inline std::size_t hash_code() const BOOST_NOEXCEPT;
获取this这个实例的hash值 - type_index实例,还支持关系运算符和运算符。对于流运算符他直接输出的是pretty_name()中的返回值。
- type_id、type_id_with_cvr、type_id_runtime是三个工厂方法,来让此命名空间中对应的模板方法来调用。
typeindex::type_id函数
函数定义:
// type_index 他是一个typedef,他可能是stl_type_index,// 也可能是ctti_type_index类型,不管是哪种,他们都有完全相同的方法,// 可以用来输出:raw_name(原始名称), pretty_name(可读名称)// 取决于编译器类型和rtti的状态,详情,请参考后面的关于这个库的内部实现细节部分template <typename T>type_index type_id(){ return type_index::type_id<T>();}
函数具体使用样例:
#include <iostream>#include <string>#include <boost/type_index.hpp>using namespace std;using namespace boost;int main(int argc, char **argv){ typeindex::type_index type; type = typeindex::type_id<int>(); cout << type.pretty_name() << endl; type = typeindex::type_id<const int>(); cout << type.pretty_name() << endl; type = typeindex::type_id<int&>(); cout << type.pretty_name() << endl; type = typeindex::type_id<const int&>(); cout << type.pretty_name() << endl; return 0;}
运行结果如下表: int
int
int
int
功能总结:
上面使用typeindex::type_id,来获取基本的int,和带有cvr(const-volatile-reference)修饰的int,最后输出名称都是int,可以说明type_id获取的类型是不带cvr修饰的原始类型。
typeindex::type_id<T>
获取是包含不带cvr修饰的T的具体类型信息的type_index实例。
typeindex::type_id_with_cvr
函数定义:
// 基本原型是template <typename T>type_index type_id_with_cvr(){ return type_index::type_id_with_cvr<T>();}
函数测试样例代码:
#include <iostream>#include <string>#include <boost/type_index.hpp>using namespace std;using namespace boost;int main(int argc, char **argv){ typeindex::type_index type; type = typeindex::type_id_with_cvr<int>(); cout << type.pretty_name() << endl; type = typeindex::type_id_with_cvr<const int>(); cout << type.pretty_name() << endl; type = typeindex::type_id_with_cvr<int&>(); cout << type.pretty_name() << endl; type = typeindex::type_id_with_cvr<const int&>(); cout << type.pretty_name() << endl; return 0;}
运行结果: int
int const
int &
int const &
功能总结:
typeindex::type_id_with_cvr<T>
获取的是带有cvr修饰的类型信息type_index实例。
typeindex::type_id_runtime
函数定义:
// 基本原型是template <typename T>type_index type_id_runtime(const T &t){ return type_index::type_id_runtime(t);}
函数测试样例代码:
#include <iostream>#include <string>#include <boost/type_index.hpp>using namespace std;using namespace boost;class IFly{public: BOOST_TYPE_INDEX_REGISTER_CLASS virtual void fly() const = 0; virtual ~IFly() {}};class Bird : public IFly{public: BOOST_TYPE_INDEX_REGISTER_CLASS void fly() const { cout << "Bird fly" << endl; }};int main(int argc, char **argv){ Bird bird; IFly &flyable = bird; typeindex::type_index type = typeindex::type_id_runtime(flyable); cout << type.pretty_name() << endl; return 0;}
运行结果: Bird
功能总结:
typeindex::type_id_runtime<T>
获取的是运行时类的具体类型。
type_index库一个具体使用样例
这个例子是使用type_index库来实现一个 带有一个参数的仿函数适配器,可以他可以适配任何带有一个参数(不管这个参数是什么类型)的函数。
#include <iostream>#include <boost/type_index.hpp>using namespace std;using namespace boost;// 一个保留cvr的具体实例// 一般来讲的话,应该讲这个类设计成一个模板类,但是也是可以不设置成模板类的。// 因为如果不设置的话,那么可以选择将部分方法导出到库里面// 好处:可以在运行时绑定任意一个含有一个参数的函数指针// 而且,调用函数的时候,类型是安全的。class type_erased_unary_function{public: // 构造器是模板(使用它非常灵活) // ParamT类型,这儿这样写ParamT最后肯定也是不带cvr特性的(我以前以为可能带的,但是最后肯定不带) template <typename ParamT> type_erased_unary_function(void (*function_ptr)(ParamT)) : function_ptr_(reinterpret_cast<void*>(function_ptr)),exact_param_t_(typeindex::type_index::type_id_with_cvr<ParamT>()) { cout << typeindex::type_id_with_cvr<ParamT>().pretty_name() << endl; } // 其实这儿有时会产生非常大的消耗的, // 不管实际参数是什么类型,对于这儿的param总是不带cvr修饰的类型 // 如果要获取实际的传入类型,可能可以使用c++ 11的完美转发机制 template <typename ParamT> void call(ParamT param) { if (exact_param_t_ != typeindex::type_id_with_cvr<ParamT>()) { throw runtime_error("Error param type..."); } reinterpret_cast<void (*)(ParamT)>(function_ptr_)(param); }private: void * function_ptr_; typeindex::type_index exact_param_t_; // 包含cvr信息};// 一个测试函数void func(int i){ cout << "i: " << i << endl;}void func2(const int i) {}int main(int argc, char **argv){ // 这个类的强大之处,是他可以接收带有一个参数的函数指针 // 主要利用模板构造器,和type_index type_erased_unary_function function(func); function.call(10); function = type_erased_unary_function(func2); return 0;}
目录:
[TOC]
- Boost type_index库使用介绍
- Boost type_index库的实现细节
- Boost Log库使用介绍
- Boost库中timer库使用介绍
- Boost Tokenizer 使用介绍
- 【Boost】boost::assign库介绍
- BOOST库介绍,安装
- Boost库的介绍
- Boost库介绍
- C++Boost库介绍
- boost库的介绍
- BOOST库介绍,安装
- BOOST库 总体介绍
- BOOST库介绍,安装
- BOOST库介绍,安装
- Boost C++库介绍
- BOOST库介绍,安装
- Boost常用库介绍
- Linux和bootstrap的学习总结
- arm-poky-linux-gnueabi-ld: unrecognized option '-Wl,-O1' 错误
- 力导向图 定义连线点击事件/样式/标注文字及源代码。
- listView设置自动滚动
- IE10首个修复补丁出现 解决ASP.NET兼容性
- Boost type_index库使用介绍
- 学点儿c#语言wpf开发
- Log4net 写文件日志与数据库日志
- ios7 - 怎么得到七牛返回的 文件和图片的 上传进度
- java读取txt文件内容
- 每日一Vim(3)——替换
- Unix高级环境编程学习之-----线程pthread_create
- linux下创建用户,制定目录,赋权限
- android5.1_SystemUI启动流程