-1

I would like to use the boost library (boost::variant) in C++ to define a vector if integers and strings. I am struggling to fill a such a vector - can someone either post an example code with fills a vector with ints and strings using the Boost library and reads elements of the vector or otherwise direct me to an example.

I searched for articles with the tage boost::variants on the SO, but could not find what I wanted.

Sid
  • 266
  • 5
  • 13
  • What did you try so far? sample code – DimChtz Mar 23 '16 at 16:06
  • If I'm correct `boost::variant, vector > v;` defines a vector `v` with int and string inputs. But I am unsure on how to fill it. – Sid Mar 23 '16 at 16:10
  • @DimChtz, I have also looked at the boost [tutorial](http://www.boost.org/doc/libs/1_55_0/doc/html/variant/tutorial.html) – Sid Mar 23 '16 at 16:13

2 Answers2

1

Here are some examples (written from memory):

typedef boost::variant<
   std::string,
   int
> StringOrInt;   // using a typedef is just for convenience

StringOrInt myVariant;
myVariant = std::string("hello");  // both of these work
myVariant = 5;

std::vector<StringOrInt> myvec;
myvec.push_back(5);
myvec.push_back(std::string("hello"));

Then to read, there are two ways. One is using boost::get, the other is using a visitor. Visitor is usually a bit more robust, but if it's a simple case, boost::get can work well.

std::string& mystr = boost::get<std::string>(myvec[0]); // this will throw if the type you requested isn't what's stored
std::string* mystr = boost::get<std::string*>(myvec[0]); // pointer version doesn't throw

Since you're probably iterating, a visitor will likely work better. You create a functor that has overloads for each type in your variant, and use boost::apply_visitor. For example:

struct MyVisitor {
    void operator()(const std::string& arg) const {
        std::cout << "It was a string";
    }

    void operator()(int arg) const {
        std::cout << "It was an int";
    }
};

MyVisitor myVisitor;
for (auto& val : myvec) {
     boost::apply_visitor(myVisitor, val);
}
Ari
  • 1,102
  • 9
  • 17
  • I am getting the compilation error: no matching function for call to apply_visitor, when I try to access elements of the vector by iterating over it. Namely, if I use the last segment of the code that you posted. Any suggestions? – Sid Mar 26 '16 at 16:50
  • could you also explain what the last part is doing, i.e. the apply visitor part? – Sid Mar 26 '16 at 17:13
  • I have updated the code. It should have had the `struct MyVisitor : public boost::static_visitor<>` as opposed to just `struct MyVisitor`. – Sid Mar 27 '16 at 20:18
  • @Sid it looks like you probably figured it out, but apply_visitor calls the visitor function, passing the variant as the argument. I don't know exactly how it works under the hood, but you can imagine it unpacks the variant, casts it to the actual type, and calls the right overload for your function. I believe it's named after the "visitor pattern". Also, feel free to edit my post so future people benefit. – Ari Mar 28 '16 at 14:16
  • Thanks Ari! I have submitted a change ... just waiting for it to be peer-reviewed and then it will be posted! – Sid Mar 29 '16 at 00:00
0

You could create a vector of Strings and then use .toString() in the positions with numbers. Or at least in Java you could create a Class VectorIntString that every instance of the class has both vectors. So when you construct the object: you will do something like this

VectorIntString vec= new VectorIntString(int a,String a, int b, String b.... ,);

So the constructor will add odds position to the Int vector and even positions to the String vector.

Crypt32
  • 12,850
  • 2
  • 41
  • 70
Augusto93
  • 1
  • 2