C++点滴--boost optional 和 variant

只是一点例子,没有什么解释;主要是给自己看,作为一个笔记而已。

boost::optional例子:

#include 
#include 


class Inner
{
  private:
    int v;

  public:
    Inner(int _v) : v(_v)
    {}

    Inner(const Inner& other) : v(other.v)
    {
      std::cout << "Inner(const Inner& other)" << std::endl;
    }

    Inner& operator=(const Inner& other)
    {
      this->v = other.v;
      std::cout << "Inner& operator=(const Inner& other)" << std::endl;
      return *this;
    }

    bool operator==(const Inner& other)
    {
      std::cout << "bool operator==(const Inner& other)" << std::endl;
      return this->v == other.v;
    }

    friend std::ostream& operator<<(std::ostream& out, const Inner& inner)
    {
      out<<"Inner("<")";
      return out;
    }

    int get_v()
    {
      return v;
    }

    void set_v(int _v)
    {
      v = _v;
    }
};

int main()
{
  boost::optional option1;
  assert(!option1);

  boost::optional option2(boost::none);
  assert(!option2);

  Inner inner3(3);

  //the following two statements are equal to each other;
  boost::optional option3(inner3);  // output: Inner(const Inner& other)  -- copy the object;
  boost::optional option4 = inner3; // output: Inner(const Inner& other)  -- copy the object;

  assert(*option3 == *option4);  // output: bool operator==(const Inner& other)  -- behaves like a pointer;

  //optional behaves like a pointer, but it holds a copy of the object instead of the pointer of the object;
  std::cout << "option3 = " << option3->get_v() << std::endl; // output: option3 = 3
  option3->set_v(8);
  std::cout << "option3 = " << option3->get_v() << std::endl; // output: option3 = 8
  std::cout << "inner3 = " << inner3.get_v() << std::endl;    // output: inner3 = 3

  boost::optional option5;
  option5 = option4;   // output: Inner(const Inner& other)  -- make a copy (copy constructor)
  std::cout << "option4 = " << option4->get_v() << std::endl; // output: option4 = 3
  std::cout << "option5 = " << option5->get_v() << std::endl; // output: option5 = 3

  option5->set_v(5);
  std::cout << "option4 = " << option4->get_v() << std::endl; // output: option4 = 3
  std::cout << "option5 = " << option5->get_v() << std::endl; // output: option5 = 5

  boost::optional option6(inner3);
  std::cout << "option6 = " << option6->get_v() << std::endl; // output: option6 = 3

  option6 = option5;  // output: Inner& operator=(const Inner& other) -- make a copy (operator=)
  std::cout << "option6 = " << option6->get_v() << std::endl; // output: option6 = 5

  return 0;
}

boost::variant例子:

#include "boost/variant.hpp"
#include 
#include   //std::for_each
#include 

class Inner
{
  private:
    int v;

  public:
    Inner(int _v) : v(_v)
    {}

    Inner(const Inner& other) : v(other.v)
    {
      std::cout << "Inner(const Inner& other)" << std::endl;
    }

    Inner& operator=(const Inner& other)
    {
      this->v = other.v;
      std::cout << "Inner& operator=(const Inner& other)" << std::endl;
      return *this;
    }

    bool operator==(const Inner& other)
    {
      std::cout << "bool operator==(const Inner& other)" << std::endl;
      return this->v == other.v;
    }

    friend std::ostream& operator<<(std::ostream& out, const Inner& inner)
    {
      out<<"Inner("<")";
      return out;
    }

    int get_v()
    {
      return v;
    }

    void set_v(int _v)
    {
      v = _v;
    }
};


class multiply_two_visitor : public boost::static_visitor<>
{
  public:
    void operator()(int& i) const
    {
      i *= 2;
    }

    void operator()(Inner& inner) const
    {
      inner.set_v(inner.get_v()*2);
    }

    void operator()(std::string& str) const
    {
      str += str;
    }
};

int main()
{
  // the semantics is like:
  //       union
  //       {
  //          int i;
  //          Inner inner;
  //          std::string s;
  //       } v;
  boost::variant<int, Inner, std::string> v;


  //////////////////////// 1. hold an object of Inner class  ////////////////////////
  Inner inner(100);

  v = inner;    // output:
                //     Inner(const Inner& other)
                //     Inner(const Inner& other)
                // copy to argument, then copy to the inside held object;
  std::cout << "v = " << v << std::endl; //output: v = Inner(100)

  //1.1 get a pointer of the object held inside;
  Inner* ptr_inner = boost::get(&v);
  ptr_inner->set_v(ptr_inner->get_v()*2);
  std::cout << "v = " << v << std::endl; //output: v = Inner(200)

  int* p1 = boost::get<int>(&v);
  std::string* p2 = boost::getstring>(&v);
  assert(p1==NULL);
  assert(p2==NULL);

  //1.2 get a reference of the object held inside;
  Inner& ref_inner = boost::get(v);
  ref_inner.set_v(ref_inner.get_v()*2);
  std::cout << "v = " << v << std::endl; //output: v = Inner(400)

  //int& ref1 = boost::get(v);                 //boost::bad_get: failed value get using boost::get;
  //std::string& ref2 = boost::get(v); //boost::bad_get: failed value get using boost::get;

  //1.3 apply visitor
  //this won't compile without any one of the 3 member functions of multiply_two_visitor;
  boost::apply_visitor(multiply_two_visitor(), v);
  std::cout << "v = " << v << std::endl; //output: v = Inner(800)



  ///////////////////////////////// 2. hold an int  /////////////////////////////////
  v = 8;
  std::cout << "v = " << v << std::endl; //output: v = 8

  //2.1 get a pointer of the object held inside;
  int* ptr_int = boost::get<int>(&v);
  *ptr_int *= 2;
  std::cout << "v = " << v << std::endl; //output: v = 16

  Inner* p3 = boost::get(&v);
  std::string* p4 = boost::getstring>(&v);
  assert(p3==NULL);
  assert(p4==NULL);

  //2.2 get a reference of the object held inside;
  int& ref_int = boost::get<int>(v);
  ref_int *= 2;
  std::cout << "v = " << v << std::endl; //output: v = 32

  //Inner& ref3 = boost::get(v);             //boost::bad_get: failed value get using boost::get;
  //std::string& ref4 = boost::get(v); //boost::bad_get: failed value get using boost::get;

  //2.3 apply visitor
  //this won't compile without any one of the 3 member functions of multiply_two_visitor;
  boost::apply_visitor(multiply_two_visitor(), v);
  std::cout << "v = " << v << std::endl; //output: v = 64


  ////////////////////////////// 3. hold a std::string  //////////////////////////////
  v = std::string("hello");
  std::cout << "v = " << v << std::endl; //output: v = hello

  //3.1 get a pointer of the object held inside;
  std::string* ptr_str = boost::getstring>(&v);
  *ptr_str += *ptr_str;
  std::cout << "v = " << v << std::endl; //output: v = hellohello

  Inner* p5 = boost::get(&v);
  int* p6 = boost::get<int>(&v);
  assert(p5==NULL);
  assert(p6==NULL);

  //3.2 get a reference of the object held inside;
  std::string& ref_str = boost::getstring>(v);
  ref_str += ref_str;
  std::cout << "v = " << v << std::endl; //output: v = hellohellohellohello

  //Inner& ref5 = boost::get(v);   //boost::bad_get: failed value get using boost::get;
  //int& ref6 = boost::get(v);       //boost::bad_get: failed value get using boost::get;

  //3.3 apply visitor
  //this won't compile without any one of the 3 member functions of multiply_two_visitor;
  boost::apply_visitor(multiply_two_visitor(), v);
  std::cout << "v = " << v << std::endl; //output: v = hellohellohellohellohellohellohellohello


  ////////////////////////////// 4. delayed visitation //////////////////////////////
  std::vectorint, Inner, std::string> > vect;
  vect.push_back(Inner(80));
  vect.push_back(81);
  vect.push_back(std::string("world"));

  //output:
  //   Inner(80)
  //   81
  //   world
  for(std::vectorint, Inner, std::string> >::iterator itr=vect.begin(); itr!=vect.end(); ++itr)
    std::cout<<*itr<//boost::apply_visitor(visitor): does not immediately apply the given visitor to any variant, but rather
  //returns a function object that can be called later.
  multiply_two_visitor visitor;
  std::for_each(vect.begin(), vect.end(), boost::apply_visitor(visitor));

  //output:
  //  Inner(160)
  //  162
  //  worldworld
  for(std::vectorint, Inner, std::string> >::iterator itr=vect.begin(); itr!=vect.end(); ++itr)
    std::cout<<*itr<///////////////////////////// 5. copy between variants ////////////////////////////
  v = inner; // output: Inner(const Inner& other)
             //         Inner(const Inner& other)
             // copy to argument, then copy to the inside held object;

  boost::variant<int, Inner, std::string> v1;
  v1 = v;    // output: Inner(const Inner& other)     -- make a copy (copy constructor)
  std::cout << "v = " << v << std::endl;   //output: v = Inner(100)
  std::cout << "v1 = " << v1 << std::endl; //output: v1 = Inner(100)

  boost::apply_visitor(multiply_two_visitor(), v1);
  std::cout << "v = " << v << std::endl;   //output: v = Inner(100)
  std::cout << "v1 = " << v1 << std::endl; //output: v1 = Inner(200)

  v1 = v;    // output: Inner& operator=(const Inner& other)   -- make a copy (operator=)
  std::cout << "v = " << v << std::endl;   //output: v = Inner(100)
  std::cout << "v1 = " << v1 << std::endl; //output: v1 = Inner(100)


  ////////////////////////// 6. default value of variant ///////////////////////////
  // this doesn't compile, because default variant will hold a default value of the 1st type;
  // the 1st type Inner, but it doesn't have the default constructor Inner::Inner();
  // To make it compile, just add the default constructor Inner::Inner();
  //boost::variant v2;

  return 0;
}

你可能感兴趣的:(C++,boost)