Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to print a boost::variant of streamable types?

Tags:

c++

boost

I feel like I'm having a serious 'Doh!' moment here...

I'm currently trying to implement:

std::ostream& operator<<(std::ostream &out, const MyType &type)

Where MyType holds a boost::variant of int, char and bool. IE: Make my variant streamable.

I tried doing this:

out << boost::apply_visitor(MyTypePrintVisitor(), type);
return out;

And MyTypePrintVisitor has a templated function that uses boost::lexical_cast to convert the int, char or bool to a string.

However, this doesn't compile, with the error that apply_visitor is not a function of MyType.

I then did this:

if(type.variant.type() == int)
out << boost::get<int> (type.variant);
// So on for char and bool
...

Is there a more elegant solution I'm missing? Thanks.

Edit: Problem solved. See the first solution and my comment to that.

like image 808
Assaf Muller Avatar asked Aug 27 '12 14:08

Assaf Muller


People also ask

What is boost :: variant?

Boost. Variant, part of collection of the Boost C++ Libraries. It is a safe, generic, stack-based discriminated union container, offering a simple solution for manipulating an object from a heterogeneous set of types in a uniform manner.

What is boost :: Apply_visitor?

boost::apply_visitor — Allows compile-time checked type-safe application of the given visitor to the content of the given variant, ensuring that all types are handled by the visitor.

How boost variant works?

boost::variant is conceptually similar to what you've done before, but by not literally using a union and instead taking a manual approach to placement construction/destruction of objects in its buffer (while handling alignment issues explicitly) it works around the restrictions that C++ has re complex types in actual ...


1 Answers

You should be able to stream a variant if all its contained types are streamable. Demonstration:

#include <boost/variant.hpp>
#include <iostream>
#include <iomanip>

struct MyType
{
    boost::variant<int, char, bool> v;
};

std::ostream& operator<<(std::ostream &out, const MyType &type)
{
    out << type.v;
}

int main()
{
    MyType t;
    t.v = 42;
    std::cout << "int: " << t << std::endl;

    t.v = 'X';
    std::cout << "char: " << t << std::endl;

    t.v = true;
    std::cout << std::boolalpha << "bool: " << t << std::endl;
}

Output:

int: 42
char: X
bool: true

If you do need to use a visitor (perhaps because some of the contained types aren't streamable), then you need to apply it to the variant itself; your snippet of code looks like it's applying it to a MyType object instead.

like image 191
Mike Seymour Avatar answered Sep 22 '22 23:09

Mike Seymour