2012-01-18 10 views
5

Ho bisogno di trovare una soluzione migliore per passare il tipo di dati in boost::variant in modo che la funzione possa recuperare elegantemente il tipo variato memorizzato. Ho realizzato un'implementazione che funziona per me, ma sono preoccupato che ci sia una via d'uscita migliore.metodo elegante per passare il tipo di dati per `boost :: variant`

// 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 

Come si può vedere dal codice sopra, il metodo implementato può gestire sia il tipo nativo che il tipo di dati personalizzato. Nel caso ideale, possiamo farlo senza introdurre il enum TypePassIn

risposta

7

È possibile utilizzare il (statico) visitor pattern, come illustrato nel tutorial di 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"]); 

} 
Problemi correlati