c++c++03boost-iterators

Using Boost zip_iterator to write two vectors to CSV file


I've got two vectors that I'd like to write to file in CSV form. I can do this "by hand" using a for-loop but I'm taking stab at using boost zip_iterator, for the first time ever. This is how far I've been able to come. (online version)

Please note that this for a legacy project and therefore I cannot use newer versions of C++ (e.g. C++11, C++14, C++17)

#include <vector>
#include <fstream>
#include <iterator>
#include <algorithm>
#include <boost/tuple/tuple.hpp>
#include <boost/iterator/zip_iterator.hpp>

typedef boost::tuples::tuple<unsigned,unsigned> DataPair;
typedef std::ostream_iterator<DataPair> DataPairOStream;

// Error messages suggest that something resembling this overload might be needed.
// This however does not solve the problem.
DataPairOStream& operator<<( DataPairOStream& stream , const DataPair& )
{
    return stream;
}

int main()
{
    std::vector<unsigned> data1( 10 , 1 );
    std::vector<unsigned> data2( 10 , 2 );

    std::ofstream outputFile( "Foo.txt" );
    DataPairOStream outputIterator( outputFile , "\n" );   // ???

    std::copy(
        boost::make_zip_iterator( boost::make_tuple( data1.begin() , data2.begin() ) ) ,
        boost::make_zip_iterator( boost::make_tuple( data1.end()   , data2.end()   ) ) ,
        outputIterator ); 
}

Snippet of the error message (the entire thing is simply too long to paste)

/usr/lib/gcc/i686-pc-cygwin/6.4.0/include/c++/bits/stream_iterator.h:198:13: error: no match for ‘operator<<’ (operand types are ‘std::ostream_iterator<boost::tuples::tuple<unsigned int, unsigned int> >::ostream_type {aka std::basic_ostream<char>}’ and ‘const boost::tuples::tuple<unsigned int, unsigned int>’)
  *_M_stream << __value;
  ~~~~~~~~~~~^~~~~~~~~~

Solution

  • This one should work good. Now ADL finds the operator<< overload because it is put in namespace boost::tuples:

    #include <vector>
    #include <fstream>
    #include <iostream>
    #include <iterator>
    #include <algorithm>
    #include <boost/tuple/tuple.hpp>
    #include <boost/iterator/zip_iterator.hpp>
    
    typedef boost::tuples::tuple<unsigned,unsigned> DataPair;
    
    namespace boost{
    namespace tuples{
    
    std::ostream & operator<<( std::ostream& stream , const DataPair& )
    {
        return stream;
    }
    
    }
    }
    
    int main()
    {
        std::vector<unsigned> data1( 10 , 1 );
        std::vector<unsigned> data2( 10 , 2 );
    
        std::ofstream outputFile( "Foo.txt" );
        std::ostream_iterator<DataPair> outputIterator( outputFile , "\n" ); 
    
        std::copy(
            boost::make_zip_iterator( boost::make_tuple( data1.begin() , data2.begin() ) ) ,
            boost::make_zip_iterator( boost::make_tuple( data1.end()   , data2.end()   ) ) ,
            outputIterator ); 
    }
    

    In practice putting operator << in std also worked, but it should NOT be done because it is undefined behaviour.