HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppModerate

Converting data when output std container via ostream_iterator

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
stdcontaineroutputostream_iteratorviawhenconvertingdata

Problem

I have a strongly typed enum and std::vector of this type.

enum class Colors { red, green, blue };
std::vector v = { Colors::blue, Colors::red };


I trying to output v to standard output via std::copy.

std::copy(v.begin(), v.end(), std::ostream_iterator(std::cout, " ");


Compilation failed because compiler do not know how to print Colors. I can define operator << for colors, but it looks too excessive for me. Then try print int values of v elements.

std::copy(v.begin(), v.end()
  , std::ostream_iterator::type>>(std::cout, " ");


Compilation failed because it is prohibited to print Colors to std::ostream_iterator. Ok. Then std::transform can help.

std::transform(v.begin(), v.end()
,   std::ostream_iterator::type>(std::cout, " ")
,   [&](Colors &c) -> std::underlying_type::type
    {
        return std::underlying_type::type(c);
    }
);


However, this lambda looks ugly. Is there neater way to copy or transform vector of Colors? Maybe boost has some way?

Of course, a loop can print, but I'd prefer to avoid explicit loop.

for(auto c : v)
{
    std::cout ::type(c) << std::endl;
}


I have a lot of different enum classes in my project. All of them I need to print out. I don't like idea to create operator << for each one individually. However, if I try to make templated operator << then I've got a global redefinition of this operator. And this is not what I actually want.

template 
std::ostream &operator ::type(_t);
    return _os;
}

Solution

It seems to me that if you want to insert an object into a stream, the "right" way to do it is normally to define an operator::type(c); anything but straightforward or simple. It's ugly and nasty.

Code Snippets

#include <iostream>
#include <vector>
#include <utility>
#include <iterator>

enum class colors { red, green, blue };
std::vector<colors> v = { colors::blue, colors::red };

std::ostream &operator<<(std::ostream &os, colors const &c) {
    return os << std::underlying_type<colors>::type(c);
}

int main() {
    std:copy(v.begin(), v.end(), std::ostream_iterator<colors>(std::cout, "\n"));
}

Context

StackExchange Code Review Q#44063, answer score: 10

Revisions (0)

No revisions yet.