0

I've read that a boost::variant is streamable if all of its variants are streamable. However,

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

std::ostream& operator<<(std::ostream& out, const std::vector<int>& v) {
    for(int i = 0; i < v.size(); ++i)
        out << " " << v[i];
    return out;
}

int main() {
    boost::variant<int, std::string > a(3);
    std::cout << a << '\n'; // OK

    std::vector<int> b(3, 1);
    std::cout << b << '\n'; // OK

    boost::variant<int, std::vector<int> > c(3);
    std::cout << c << '\n'; // ERROR
}

fails to compile. Why?

Versions:

  • Boost 1.53
  • GCC 4.6.3
MWB
  • 11,740
  • 6
  • 46
  • 91

1 Answers1

6

I haven't checked the documentation of serialization, but I'm pretty sure that operator<< for the types of boost::variant needs to be either found by Argument Dependent Lookup or else be present in boost namespace.

This works:

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

namespace boost {

    std::ostream& operator<<(std::ostream& out, const std::vector<int>& v) {
        for(int i = 0; i < v.size(); ++i)
            out << " " << v[i];
        return out;
    }

}

int main() {
    boost::variant<int, std::string > a(3);
    std::cout << a << '\n';

    {
    using namespace boost;
    std::vector<int> b(3, 1);
    std::cout << b << '\n';
    }

    boost::variant<int, std::vector<int> > c(3);
    std::cout << c << '\n';
}

Output:

3
 1 1 1
3
jrok
  • 54,456
  • 9
  • 109
  • 141
  • Still confused. Why isn't my `operator<<` found via Koenig lookup? (Strictly speaking, my question was "why") Defining functions in `boost` for objects that are not from Boost seems like a bad practice. – MWB Jan 03 '14 at 19:43
  • 1
    @MaxB because argument dependent lookup looks in the related namespaces, being `::std` (from std::vector and/or std::ostream), only – sehe Jan 03 '14 at 22:09