Search code examples
c++ostringstreamboost-tuples

How to write a `<<` operator for boost::tuple?


In the sample code below, it shows that boost::tuple can be created implicitly from the first template argument. Because of that I am not able to write a << operator as it becomes ambiguous.

Also I don't understand why ostringstream& << float is also ambiguous. This does not have any implicit construction. Why does this also give ambiguous error?

#include <iostream>
#include <boost/tuple/tuple.hpp>
#include <sstream>
#include <string>

using namespace std;

class Myclass
{
};

typedef boost::tuple<int,float,Myclass> Mytuple;

ostringstream& operator<<(ostringstream& os_, Mytuple tuple_)
{
  float f = tuple_.get<1>();
  //os_ << (int)tuple_.get<0>(); // Error because int is implicitly converted into Mytuple. WHYY?
  //os_ << tuple_.get<1>();      // No Clue Why this is ambiguous.
  //os_ << tuple_.get<2>();      // Error because no matching operator. Fine.
  return os_;
}

int main()
{
  Mytuple t1;
  t1 = 3;      // Working because int is implicitly converted into Mytuple!! WHY?
  //t1 = 3.0f; // Error because no matching constructor. Fine.
  return 0;
}

Error Mesasge:

tupleTest2.C:18: error: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:


Solution

  • The problem is not with the tuple, but with your operator. This works fine :

    ostream& operator<<(ostream& os_, Mytuple tuple_)
    {
        os_ << tuple_.get<0>(); // Error because int is implicitly converted into Mytuple. WHYY?
        os_ << tuple_.get<1>();      // No Clue Why this is ambiguous.
        //os_ << tuple_.get<2>();      // Error because no matching operator. Fine.
        return os_;
    }
    

    The problem is that the ostringstream inherit operator<< from ostream, which has this signature : ostringstream& operator<<(ostringstream& os_, Mytuple tuple_) is allowed. Then the

    ostream& operator<<(ostream& os, T t)
    

    (change T with all available types in c++, see operator<< reference page

    EDIT

    Here is a simplified example (without a tuple) :

    ostringstream& operator<<(ostringstream& os_, Mytuple tuple_)
    {
        const int i = tuple_.get<0>();
        os_ << i; // error in this line
        return os_;
    }
    

    and the error is now :

    dfg.cpp: In function ‘std::ostringstream& operator<<(std::ostringstream&, Mytuple)’:
    dfg.cpp:18: error: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second:
    /usr/lib/gcc/i386-redhat-linux/4.3.0/../../../../include/c++/4.3.0/bits/ostream.tcc:111: note: candidate 1: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>]
    dfg.cpp:14: note: candidate 2: std::ostringstream& operator<<(std::ostringstream&, Mytuple)
    

    The above error message says : it is not possible to choose between two operators operator<<(ostream&,...) and operator<<(ostringstream&,...). This also raises another question : why on earth do you needoperator<<(ostringstream&,...)`?