Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

elegant method to pass the data type for `boost::variant`

Tags:

c++

boost

I need to find a better solution to pass the data type into boost::variant so that the function can retrieve the stored variate type elegantly. I have put up an implementation that works for me but I am concern there is a better way out there.

// file name: p192.cpp
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <boost/variant.hpp>

using namespace std;

enum TypePassIn
{
  INT_TYPE,
  DOUBLE_TYPE,
  STRING_TYPE,
  PERSON_TYPE,
  LAST_TYPE = PERSON_TYPE
};

struct Person
{
  Person(int _age, string _name) : age(_age), name(_name) {}    
  int age;
  string name;
};

void PrintVariant(map<string, boost::variant<int, double, string, Person> > _mapValues, TypePassIn tpi)
{
  switch(tpi)
    {
    case INT_TYPE:
      cout << boost::get<int>(_mapValues["int"]) << endl;
      break;
    case DOUBLE_TYPE:
      cout << setprecision (15) << boost::get<double>(_mapValues["double"]) << endl;
      break;
    case STRING_TYPE:
      cout << boost::get<string>(_mapValues["string"]) << endl;
      break;
    case PERSON_TYPE:
      cout << "Age: " << (boost::get<Person>(_mapValues["Person"])).age;
      cout << ", Name: " << (boost::get<Person>(_mapValues["Person"])).name << endl;
      break;
    default:
      break;
    }
}

int main(void)
{ map<string, boost::variant<int, double, string, Person> > mapValues;

  mapValues["int"] = 10;
  PrintVariant(mapValues, INT_TYPE);

  mapValues["double"] = 100.99;
  PrintVariant(mapValues, DOUBLE_TYPE);

  mapValues["string"] = "Hello world";
  PrintVariant(mapValues, STRING_TYPE);

  mapValues["Person"] = Person(10, "Tom");
  PrintVariant(mapValues, PERSON_TYPE);    
}    

~/Documents/C++/boost $ ./p192
10
100.99
Hello world
Age: 10, Name: Tom

As you can see from the code above, the implemented method can handle both native type and customized data type. In the ideal case, we can do it without introducing the enum TypePassIn

like image 281
q0987 Avatar asked Jan 18 '12 17:01

q0987


1 Answers

You can use the (static) visitor pattern, as shown in the tutorial of Boost.Variant.

struct VariantPrinter : boost::static_visitor<void>
{
    void operator()(int int_val)
    {
        std::cout << int_val << std::endl;
    }
    void operator()(double double_val)
    {
        std::cout << std::setprecision(15) << double_val << std::endl;
    }
    // etc.
};

void PrintVariant(const boost::variant<...>& the_variant)
{
    boost::apply_visitor(VariantPrinter(), the_variant);
}

int main()
{
    std::map<std::string, boost::variant<...> > mapValues;

    mapValues["int"] = 10;
    PrintVariant(mapValues["int"]);

}
like image 102
kennytm Avatar answered Nov 15 '22 05:11

kennytm