boost::any 为什么要用 static_cast + type_info 呢?

boost::any 为什么要用 static_cast + type_info 呢?

关于boost::any,今天心血来潮,顺手实现了一个。不想加有关type_info的东西,所以自我创造了一个用dynamic_cast的版本,仅供学习。
要用当然要boost::any的嘛。

关于模板,首先说两条:

1. 类模板
   (缺点)类模板不能自动推导模板参数(意思是当要用到某个模板类,比如A,那么你使用的时候一定要有模板参数,比如A<int>,编译器不能自动推导),只能通过特化模板而是编译器选择合适的特化版本,
   (优点)类模板可以通过类模板把推导后的模板参数输出,通常使用 typedef _Type value; 。

2. 函数模板
   (优点)函数模板可以自动推导模板参数(意思是你顶一个模板函数,比如f,那么使用的时候不一定要有模板参数,比如f(123),编译器会自动推导123为int),当然这里可以靠函数重载和编译器匹配顺序,来决定很多事情。
   (缺点)函数模板不能输出推导后的类型。
 1  struct  any
 2  {
 3       struct  content
 4      {};
 5 
 6      template < typename _U >
 7       struct  impl :  public  content
 8      {
 9          _U _u;
10 
11          impl( const  _U &  u)
12              : _u(u)
13          {}
14 
15          typedef _U type;    
16      };
17 
18      template < typename _U >
19      any( const  _U &  c)
20          : _t( new  impl < _U > (c))
21      {}
22 
23      content *  _t;
24  };

那么要实现any,any本身不是类模板,所以要接受任何参数,那么其构造函数必须是函数模板,但是函数模板不能导出推导后的类型,那么需要靠类模板来保存类型信息。


1  struct  any
2  {
3      template < typename _U >
4      any( const  _U &  c)
5      {}
6  };

可以看出,上面的any定义可以接受任何类型的参数,比如 any t1(1); any t2(1.0); 注意1和1.0不一样。 但是输入的东西没有保存起来,起不到一个任意类型变量的作用(就是个空壳)。所以继续修改,

 1  struct  any
 2  {
 3 
 4      template < typename _U >
 5       struct  impl
 6      {
 7          _U _u;
 8 
 9          impl( const  _U &  u)
10              : _u(u)
11          {}
12 
13          typedef _U type;    
14      };
15 
16      template < typename _U >
17      any( const  _U &  c)
18          : _t( new  impl < _U > (c))
19      {}
20 
21      impl < ??? >*  _t;
22  };

前面说过,类模板可以保存类型信息,所以加入了一个 impl 的类模板,通过any的构造函数推导出的类型,将参数的类型保存在impl里面。看到最后一样的问号了吧,哪里要写什么呢?
any其实不知道他自己里面是什么东西呀,所以为了让any知道,定义一个类A,然后让impl继承它,那么这个A就是所有impl<>的父类了,不管impl里面是什么,都是一个A。当然起名A不好听,换个吧。

 1  #include  < typeinfo >
 2 
 3  using   namespace  std;
 4 
 5  struct  any
 6  {
 7       struct  content
 8      {
 9           virtual   ~ content() {};
10      };
11 
12      template < typename _U >
13       struct  impl :  public  content
14      {
15          _U _u;
16 
17          impl( const  _U &  u)
18              : _u(u)
19          {}
20 
21          typedef _U type;    
22      };
23 
24      template < typename _U >
25      any( const  _U &  c)
26          : _pc( new  impl < _U > (c))
27      {}
28 
29       ~ any()
30      {
31          delete _pc;
32      }
33 
34      template < typename _T >
35      _T &   get ()
36      {
37          impl < _T >*  p  =  dynamic_cast < impl < _T >*> (_pc);
38           if ( 0   ==  p)
39               throw  bad_cast();
40           return  p -> _u;
41      }
42 
43  private :
44      content *  _pc;
45  };
46 
47  void  main()
48  {
49      any a( 10 );
50      any b( 1.0 );
51       int  x  =  a. get < int > ();
52       double  y  =  b. get < double > ();
53  }


现在可以看到, content代替了那个不知道些什么类型的???,这个技术名字叫类型消除技术,在boost里面用的很多,也算是一个经典的技术了。

你可能感兴趣的:(boost::any 为什么要用 static_cast + type_info 呢?)