5

What's the C++ way to print or cout a C++ standard library container to the console, to view its contents?

On a separate note, why doesn't the C++ library actually overload the << operator for you? Any history behind it?

hlin117
  • 20,764
  • 31
  • 72
  • 93
  • 1
    Iterate through the elements and print each one? Maybe you could show an example of what you're asking. – Retired Ninja Mar 02 '15 at 05:34
  • Are you printing objects which you want to get a specific value or are you printing simple data types? – Hayden Mar 02 '15 at 05:37
  • 1
    You might try a [pretty printer](http://louisdx.github.io/cxx-prettyprint/) – chris Mar 02 '15 at 05:41
  • There are quite a few similar existing questions, with requirements and answers at different levels of complexity and completeness... e.g. http://stackoverflow.com/questions/4850473/pretty-print-c-stl-containers?lq=1 – Tony Delroy Mar 02 '15 at 05:43
  • @RetiredNinja: I would just like a nice way to print objects out, similar to how you could `print list` or `print set` in python. No order required. – hlin117 Mar 02 '15 at 06:03

3 Answers3

4

Overloading the operator<< for ostream is the way to go. Here's one possibility:

template <class container>
std::ostream& operator<<(std::ostream& os, const container& c)
{
    std::copy(c.begin(),
              c.end(),
              std::ostream_iterator<typename container::value_type>(os, " "));
    return os;
}

Then you can simply write:

std::cout << SomeContainer << std::endl;

Here are some other actually really nice solutions: Pretty-print C++ STL containers

Community
  • 1
  • 1
Emil Laine
  • 41,598
  • 9
  • 101
  • 157
1

The simplest way is to use the range-based for statement. For example

#include <iostream>
#include <string>
#include <vector>
#include <iterator>

template <class Container>
std::ostream & display( const Container &container, 
                        const char *s = " ",
                        std::ostream &os = std::cout )
{
    for ( const auto &value : container )
    {
        os << value << s;
    }

    return os;
}

int main()
{
    int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    std::vector<int> v( std::begin( a ), std::end( a ) );

    display( a, "; " );
    std::cout << std::endl;

    display( v );
    std::cout << std::endl;

    return 0;
}

The program output is

0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 
0 1 2 3 4 5 6 7 8 9 

However a more flexibale approach will be to use standard algorithm std::copy. In this case you can set the displayed range yourself and use reverse iterators. Also you can write the function such a way that it would get additional information.

why doesn't the C++ library actually overload the << operator for you?

Because any user can use his own approach to output a container as you can see from the output of my demonstrative program. In fact a container is a user-defined class and it is the user who should overload operator <<. There is exceptions for std::string and std::bitset but strings and bitsets are outputed as one entity without intermediate separates similarly to fundamental types.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • I feel like C++ should provide some standard implementations for `operator<<`. Python at least does this for its standard data structures. – hlin117 Mar 02 '15 at 20:24
0

For variety, make an adaptor, something like

template< typename T >
struct SequencePrinter
{
    const T& t;
    // ...
};
template< typename T >
SequencePrinter<T> sequence_printer(const T&);
template< typename T >
ostream& operator<<(ostream&, SequencePrinter<T>);
int main() {
    vector<int> v;
    // ...
    cout << sequence_printer(v) << endl;
}

This allows the usual << notation, but doesn't try to force a particular choice of what << should mean with a sequence. It could, of course, be made fairly configurable too.