boost::any

4.6.1 万能类型boost::any

2009-07-08 11:51 白乔/左飞 电子工业出版社 我要评论(0) 字号: T | T

《把脉VC++》第4章对象的赋值与转换,本章介绍了对象的初始化(从无到有)和赋值(从A到B)问题,讨论如何对对象进行类型上的、数值上的转换,并结合我们常常接触到的数学运算和字符编码问题展开讨论。本节讲述的是万能类型boost::any。

AD:

4.6  使用第三方库

以上介绍了Visual C++对对象赋值、转换及字符编码转换的方法,实际上还有一些好用的第三方类库用以辅助C++程序员完成对象处理,比较著名的就是boost。本节简单介绍boost库中与数值相关的boost::any、boost::lexical_cast,以及有理数类boost::rational。

4.6.1  万能类型boost::any

boost库提供了any类,boost::any是一个能保存任意类型值的类,这一点有点像variant类型,不过variant由于采用了一个巨大的union,效率非常低。而boost利用模板,保存的时候并不改变值的类型,只是在需要的时候才提供方法让用户进行类型判断及取值。

boost::any几乎可以用来存储任何数据类型:

 
  1. boost::any ai, as;  
  2. ai = 100;  
  3. as = string("hello"); 

需要的时候,我们又可以使用any_cast将原来的数据还原:

 
  1. int i = boost::any_cast<int>(ai);  
  2. string s = boost::any_cast<string>(as); 

当这种转换发生类型不匹配时,会有异常bad_any_cast发生:

 
  1. try 
  2. {  
  3.     int i = boost::any_cast<int>(as);  
  4. }  
  5. catch(boost::bad_any_cast & e)  
  6. {  

在传统的C++程序中,为了支持各种数据类型,我们不得不使用万能指针"void *",但是很遗憾的是,基于万能指针的转换是不安全的,"void*"缺少类型检查。所以,我们建议大家尽量使用any类。

现在动手

编写如下程序,体验如何使用boost::any来完成对象类型转换。

【程序 4-10】使用boost::any完成对象类型转换

 
  1. 01  #include "stdafx.h" 
  2. 02  #include "boost/any.hpp" 
  3. 03  #include <string>  
  4. 04    
  5. 05  using namespace std;  
  6. 06  using namespace boost;  
  7. 07    
  8. 08  class Cat  
  9. 09  {  
  10. 10  };  
  11. 11    
  12. 12  void print(any it)  
  13. 13  {  
  14. 14      if(it.empty())  
  15. 15      {  
  16. 16          printf("nothing!\r\n");  
  17. 17          return;  
  18. 18      }  
  19. 19    
  20. 20      if(it.type() == typeid(int))  
  21. 21      {  
  22. 22          printf("integer: %d\r\n", any_cast<int>(it));  
  23. 23          return;  
  24. 24      }  
  25. 25    
  26. 26      if(it.type() == typeid(string))  
  27. 27      {  
  28. 28          printf("string: %s\r\n", any_cast<string>(it).c_str());  
  29. 29          return;  
  30. 30      }  
  31. 31    
  32. 32      if(it.type() == typeid(CString))  
  33. 33      {  
  34. 34          _tprintf(_T("CString: %s\r\n"), any_cast<CString>(it));  
  35. 35          return;  
  36. 36      }  
  37. 37    
  38. 38      if(it.type() == typeid(Cat))  
  39. 39      {  
  40. 40          _tprintf(_T("oops! a cat!\r\n"));  
  41. 41          return;  
  42. 42      }  
  43. 43  }  
  44. 44    
  45. 45  int main()  
  46. 46  {  
  47. 47      print(100);  
  48. 48    
  49. 49      any as[] = {any(), 100, string("hello"), CString("world"), Cat()};  
  50. 50      for(int i = 0; i < sizeof(as) / sizeof(as[0]); i++)  
  51. 51      {  
  52. 52          print(as[i]);  
  53. 53      }  
  54. 54    
  55. 55      return 0;56 } 

结果输出如图4-18所示。

 
 
 

目对应于光盘中的目录"\ch04\BoostAnyTest"。


<think>好的,我现在需要帮助用户解决关于boost::any判断类型的问题。首先,用户可能在使用boost::any时遇到了如何确定存储的具体类型的需求。我需要先回忆一下boost::any的基本用法和相关方法。 首先,boost::any是一个可以存储任意类型数据的容器,类似于C++17的std::any。用户想知道如何判断其中存储类型。常见的方法是使用type()成员函数获取类型信息,然后与目标类型进行比较。比如使用typeid(int)来检查是否是整数类型。 接下来,我需要考虑用户可能的实际应用场景。例如,他们可能需要在运行时根据存储的不同类型执行不同的操作。这时候可能需要结合any_cast来进行类型换,但需要注意异常处理,因为错误的类型换会抛出boost::bad_any_cast异常。 然后,用户可能需要更复杂的类型判断,比如处理继承关系。这时候typeid可能不够,需要使用其他方法,比如在类型注册时添加自定义信息,或者使用模板和类型特征来判断。这部分可能对高级用户更有帮助,但需要解释清楚。 另外,用户可能对性能有疑问,比如type()和typeid的比较是否高效。需要说明typeid的比较是快速的,因为它只是比较类型信息指针,不会影响性能。 还需要考虑错误处理的情况,比如当any为空时,调用type()会导致未定义行为,应该提醒用户在使用前检查empty()方法。 可能的误区是用户可能尝试直接使用typeid来判断,但必须通过boost::any的type()方法获取存储类型信息,再进行比较。需要强调这一点,避免用户直接对any对象使用typeid。 最后,总结几种方法,给出代码示例,帮助用户理解如何正确使用type()和any_cast,以及如何处理异常情况。确保步骤清晰,示例正确,符合用户的实际使用需求。</think>在Boost库中,`boost::any` 类型判断需要结合类型查询和类型换操作。以下是具体实现方法: $$ \text{类型判断逻辑} \\ \text{is\_type} = \begin{cases} \text{true}, & \text{any.type() == typeid(T)} \\ \text{false}, & \text{otherwise} \end{cases} $$ **核心方法:** 1. **直接类型比对** ```cpp boost::any value = 42; if(value.type() == typeid(int)) { std::cout << "存储的是int类型"; } ``` 2. **安全类型换(推荐)** ```cpp try { int num = boost::any_cast<int>(value); // 换成功则类型匹配 } catch(const boost::bad_any_cast&) { // 类型不匹配时捕获异常 } ``` **高级用法:** 3. **模板辅助判断** ```cpp template<typename T> bool is_type(const boost::any& val) { return val.type() == typeid(T); } // 使用示例 if(is_type<std::string>(value)) { // 处理字符串类型 } ``` 4. **继承关系判断(需RTTI支持)** ```cpp class Base {}; class Derived : public Base {}; boost::any obj = Derived(); if(typeid(Base).is_before(obj.type())) { // 检查继承关系 Base* ptr = boost::any_cast<Base*>(obj); } ``` **性能对比表:** | 方法 | 时间复杂度 | 异常安全 | 适用场景 | |---------------------|------------|----------|--------------------------| | `type()`直接比对 | O(1) | 安全 | 简单类型判断 | | `any_cast`尝试换 | O(1) | 需捕获 | 需要获取值的场景 | | 模板辅助函数 | O(1) | 安全 | 需要重复类型判断 | **典型错误示例:** ```cpp boost::any data = 3.14; // 错误:直接比较type_info对象 if(typeid(data) == typeid(double)) // 永远为false,应使用data.type() // 正确: if(data.type() == typeid(double)) ``` **重要注意事项:** 1. 确保编译时开启RTTI(`/GR` in MSVC, `-frtti` in GCC) 2. 空any对象调用`.type()`会返回`typeid(void)` 3. 跨DLL边界使用时需保证类型信息一致性 **扩展应用:结合variant实现类型分发** ```cpp void handle_any(const boost::any& val) { if(auto p = boost::any_cast<int>(&val)) { // 处理int类型 } else if(auto p = boost::any_cast<std::string>(&val)) { // 处理string类型 } else { // 未知类型处理 } } ``` 建议优先使用`boost::any_cast`的指针形式进行安全判断,其时间复杂度为$O(1)$且无需异常处理: ```cpp if(auto ptr = boost::any_cast<int>(&value)) { // 类型匹配时ptr非空 int num = *ptr; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值