variant有点类似于C++的联合体union,但是它比union强大,union只能容纳原始类型,variant可以容纳任意类型
源代码看了蛮久,没太看懂,这就是模板的坏处了
简单看下使用举例
class CTest
{
 char szTest_[40];
};
typedef variant<int, float, string, CTest> var_t;
var_t也相当于一个联合体,可以容纳三个中的一个,当然内存大是其中一个最大的。另外还得加上一些variant自己的大小,var_t测试的大小是44
STATIC_ASSERT(sizeof(variant1) == 44);
赋值也很简单
CTest aa;
 var_t variant1(aa);
 variant1 = 10;
直接使用等号,类型最匹配的即可。
访问与any类似
try
 {
  float f1 = get<float>(variant1);
 }
 catch(boost::bad_get&)
 {
 }
转换不成功就会抛出异常,另外它也可以通过转换为指针保证不会抛出异常的方式
// 也可以转换成指针,转换成指针不会抛出异常,但是如果类型不匹配指针指针所值的内容是
 float* pFloat=boost::get<float>(&variant1);
 CTest* pTest = boost::get<CTest>(&variant1);
int* pInt = boost::get<int>(&variant1);
assert(NULL == pFloat && NULL == pTest && NULL != pInt && (10 == *pInt));
另外它还提供了一种更安全的访问方式。需要继承自stati_visitor,static_visitor的默认模板方式是void,如果是int,operator()的返回类型就需要也使用int
class var_print: public static_visitor<>
{
public:
 template<typename T>
 void operator()(T& i) const
 {
}
 template<>
 void operator()(double& i) const
 {
  // do something for i
 }
 template<>
 void operator()(int& i) const
 {
}
 template<>
 void operator()(CTest& i) const
 {
 }
};
访问
var_print vp;
apply_visitor(vp, variant1);
这样variant1就会安全的转换到对应的函数重载中了。对相应的变量执行相关操作了。
里面的实现大概猜到一些,variant存储两个类型变量
 which_t which_;// 该参数表示当前存储的值是哪个类型
storage_t storage_;// 该参数是存储真正值的变量,在初始化的时候会分配内存,当然是根据variant中几个模板参数最大的一个内存进行分配的。
然后赋值的过程
template <typename T>
    variant(T& operand)
    {
        convert_construct(operand, 1L); // 拷贝赋值
    }
template <typename T>
    void convert_construct(
          T& operand
        , int
        , mpl::false_ = mpl::false_() // is_foreign_variant
        )
    {
        // NOTE TO USER :
        // Compile error here indicates that the given type is not 
        // unambiguously convertible to one of the variant's types
        // (or that no conversion exists).
        //
        indicate_which(
              initializer::initialize(
                  storage_.address()
                , operand
                )
             );
    }
// 调用initializer::initialize,然后将返回值赋给whtich_
void indicate_which(int which_arg) BOOST_NOEXCEPT
    {
        which_ = static_cast<which_t>( which_arg );
    }
调用initializer::initialize的过程
static int initialize(void* dest, param_T operand)
            {
                typedef typename boost::detail::make_reference_content<
                      recursive_enabled_T
                    >::type internal_T;
                new(dest) internal_T(operand);
                return BOOST_MPL_AUX_VALUE_WKND(index)::value; // which
            }
是在storage_的地址的地方调用new(dest) internal_T(operand);。拷贝构造函数,dest的地址就是storage_address(),operand就是赋值的那个值。此处value是怎么取的没太看懂。反正就赋值给了which_了。
 
                   
                   
                   
                   
                             
       
           
                 
                 
                 
                 
                 
                
               
                 
                 
                 
                 
                
               
                 
                 扫一扫
扫一扫
                     
              
             
                   4554
					4554
					
 被折叠的  条评论
		 为什么被折叠?
被折叠的  条评论
		 为什么被折叠?
		 
		  到【灌水乐园】发言
到【灌水乐园】发言                                
		 
		 
    
   
    
   
             
            


 
            