Boost--variant (C++中的union)


  • union联合体类型的问题

    • 只能用于内部类型,这使得union在C++中几乎没有用
  • 所以boost提供了variant,相当于是C++中的union

#include "boost/variant.hpp"
#include 
#include 
#include 
#include 

using namespace std;

class DoubleVisitor : public boost::static_visitor<> {
public:
   void operator() (int& i) const {  
       i += i;
   }
   void operator() (string& str) const { 
       str += str;
   }
};

void Double( boost::variant u) {
}

int main()
{
//   C union:
   union {int i; float f;} u;   // u要么包含一个int,要么包含一个float
   u.i = 34;
   cout << u.i << endl; 
   u.f = 2.3;  // u.i被覆盖
   cout << u.i << endl;  // 输出无效的结果
// 问题:只支持内部类型

   //union {int i; string s;} u;   //  比如string就编译不了


// variant是C++中的union
   boost::variant u1, u2;
   u1 = 2;
   u2 = "Hello";
   cout << u1 <<  endl;
   cout << u2 << endl;
   //u1 = u1 * 2;  // variant类型没有重载*,不能直接进行操作
   u1 = boost::get(u1) * 2;    // 使用get() 返回一个int的引用
	                                 // 如果是variant, get()返回int的指针
	                                 
   cout << boost::get(u1) <<  endl;  // output: 64
   //cout << boost::get(u1) << endl;  // 崩。 variant是带鉴别能力的union
   //  如果检索失败, get() 返回空指针或者抛出一个异常: bad_get
   u1 = "good";  // u1 变成一个string
   u1 = 32;   // u1 变成一个int

	
	// variant永远不会为空
   boost::variant u3;
   cout << boost::get(u3) <<  endl;
   
   // 使用get的问题是我们并不总是知道保存在variant中的类型是什么

   //这个时候可以使用visitor
    // 定义仿函数,为variant的不同类型重载函数调用运算符
   boost::apply_visitor( DoubleVisitor(), u1 );
   cout << boost::get(u1) <<  endl;  // output: 128

   boost::apply_visitor( DoubleVisitor(), u2 );
   cout << boost::get(u2) << endl; // output: HelloHello

   std::vector< boost::variant > arr;
   arr.push_back("good");
   arr.push_back(25);
   arr.push_back("bad");
   for (auto x : arr) {
       boost::apply_visitor( DoubleVisitor(), x);    //会根据variant中存的不同类型,进行不同的操作
   }
}