Question

I was going through boost::variant and wondering how can I make following to work ?

typedef boost::variant<int,std::string> myval;
int main()
{

std::vector<myval> vec;

std::ifstream fin("temp.txt");

//How following can be achieved ?
std::copy(std::istream_iterator<myval>(fin), //Can this be from std::cin too ?
          std::istream_iterator<myval>(),
          std::back_inserter(vec));   
}

For classes data members we have option to overload >> operator, but how to do this with myval ?

Was it helpful?

Solution

You can overload operator>> for variant just like for any other type. But it is up to you to implement the logic to decide what type is read from the stream and stored in variant. Here's a complete example of how you might go about it:

#include "boost/variant.hpp"
#include <iostream>
#include <cctype>
#include <vector>
#include <string>

typedef boost::variant<int, std::string> myval;

namespace boost { // must be in boost namespace to be found by ADL
std::istream& operator>>(std::istream& in, myval& v)
{
    in >> std::ws;      // throw away leading whitespace
    int c = in.peek();
    if (c == EOF) return in;  // nothing to read, done

    // read int if there's a minus or a digit
    // TODO: handle the case where minus is not followed by a digit
    // because that's supposed to be an error or read as a string
    if (std::isdigit(static_cast<unsigned char>(c)) || c == '-') {
        int i;
        in >> i;
        v = i;
    } else {
        std::string s;
        in >> s;
        v = s;
    }
    return in;
}
} // namespace boost

// visitor to query the type of value
struct visitor : boost::static_visitor<std::string> {
    std::string operator()(const std::string&) const
    {
        return "string";
    }
    std::string operator()(int) const
    {
        return "int";
    }
};

int main()
{
    std::vector<myval> vec;
    std::copy(
        std::istream_iterator<myval>(std::cin),
        std::istream_iterator<myval>(),
        std::back_inserter(vec));

    std::cout << "Types read:\n";
    for (const auto& v : vec) {
        std::string s = boost::apply_visitor(visitor(), v);
        std::cout << s << '\n';
    }
}

Example input: 1 2 3 hello 4 world

Output:

Types read:
int
int
int
string
int
string

OTHER TIPS

myval is just a type. You overload operators based on types.

std::istream &operator >>(std::istream &stream, myval &val)
{
    //Put stuff here.
}

As for what to put there, that's entirely up to you and what you expect or require there to be in the stream.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top