Accumulating into std::ostream using std::accumulate - c++

I am trying to use std::accumulate to write into std::ostream in the operator<< (this is just a minimum example, I know this could be implemented much simpler):
#include <iterator>
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
struct A {
A() : v(std::vector<int>()){};
std::vector<int> v;
A(std::vector<int> v) : v(v){};
friend std::ostream& operator<<(std::ostream& stream, A& a);
};
std::ostream& operator<<(std::ostream& stream, A& a) {
// I need something similar to
// return std::accumulate(a.v.begin(), a.v.end(), "",
std::ostream_iterator<int>(stream, " "));
// or:
// return std::accumulate(a.v.begin(), a.v.end(), stream,
[]()->{});
}
int main(int argc, char* argv[]) {
std::vector<int> v({1, 2, 3, 4, 5});
A a(v);
std::cout << a << std::endl;
return 0;
}
How can I make this operator work?

Don't use accumulate, use copy:
std::ostream& operator<<(std::ostream& stream, A& a) {
std::copy(a.v.begin(), a.v.end(), std::ostream_iterator<int>(stream, " "));
}
This is actually one of the examples at the above reference page (though for std::copy, not for std::ostream_iterator.

You may abuse of std::accumulate like this:
std::ostream& operator<<(std::ostream& stream, A& a) {
return std::accumulate(a.v.begin(), a.v.end(), std::ref(stream),
[](std::ostream& stream, int e)
{ return std::ref(stream << " " << e); });
}
Demo

It can be done:
// Using accumulate
std::ostream& out_acc(const std::vector<int>& is, std::ostream& out)
{
return std::accumulate(is.begin(),
is.end(),
std::ref(out),
[](std::ostream& os, int i) -> std::ostream&
{ return os << i << ", "; });
}
// Using for_each
std::ostream& out_for(const std::vector<int>& is, std::ostream& out)
{
std::for_each(is.begin(),
is.end(),
[&](int i)
{ out << i << ", "; });
return out;
}
for_each is the natural choice, as you don't really care much about the accumulated value.

Since you mentioned that for_each could be used, too (and accumulate was just mentioned to confuse the Martians):
std::ostream& operator<<(std::ostream& stream, const A& a) {
std::for_each(begin(a.v), end(a.v), [](int i){ std::cout << i << " "; });
return stream;
}
Beware: You'll have a trailing space here. You'll need to handle the first or last element differently, if you want to avoid that (for instance by using a counter in the lambda).

Related

How to custom Class to_string for std::cout

I find following boost code
for (auto entry : boost::make_iterator_range(boost::filesystem::directory_iterator(dir_path), {})) {
std::cout << entry << std::endl;
}
entry can be output with dir path, I guess c++ has feature like java Class#toString to custom output string, I try following code:
class C {
str to_string() {
return "prpr";
}
};
TEST_F(FileTest, Draft1) {
C c;
std::cout << c << std::endl;
}
I expect output "prpr", but it doesn't work, how to fix it?
C++ doesn't call any "to_string" or similar function automatically. Instead you must overload the operator<< function for your class:
class C
{
public:
friend std::ostream& operator<<(std::ostream& os, C const& c)
{
return os << "prpr";
}
};
If you want to pass a class to std::cout you need to overload the << operator for std::ostream in your class.
class C {
friend std::ostream& operator<<(std::ostream& os, const C& c);
};
std::ostream& operator<<(std::ostream& os, const C& c){
os<<"prpr";
return os;
}

How to create a lambda for ostream?

I thought the call of the operator<< would generate a two-parameter function call. So, why does this not compile, then?
#include <iostream> // ostream
#include <iomanip> // setw, setfill
using std::ostream; using std::setw; using std::setfill;
struct Clock {
int h_, m_, s_;
Clock(int hours, int minutes, int seconds)
: h_{hours}, m_{minutes}, s_{seconds} {}
void setClock(int hours, int minutes, int seconds) {
h_ = hours; m_ = minutes; s_ = seconds;
}
friend ostream& operator<<(ostream&os, const Clock& c) {
auto w2 = [](ostream&os, int f) -> ostream& {
return os << setw(2) << setfill( '0' ) << f; };
return os << w2(c.h_) <<':'<<w2(c.m_)<<':'<<w2(c.s_); // ERROR
}
};
The error is (gcc-6)
$ g++-6 -std=gnu++1y ...
file.cpp: In function β€˜std::ostream& operator<<(std::ostream&, const Clock&)’:
file.cpp:745:33: error: no match for call to β€˜(operator<<(std::ostream&, const Clock&)::<lambda(std::ostream&, int)>) (const int&)’
return os << w2(c.h_) <<':'<<w2(c.m_)<<':'<<w2(c.s_);
^
I also tried the call os << w2(os,c.h_) but gcc and I agreed that was nonsense. Also I tried the lambda as auto as possible:
auto w2 = [](auto&os, auto f) {
return os << setw(2) << setfill( '0' ) << f; };
also no luck.
Any hints?
I thought the call of the operator<< would generate a two-parameter function call.
No, invoking an overloaded operator<< is basically the same as invoking a binary function:
a << b;
// is equivalent to
operator<<(a, b);
// or to
a.operator<<(b);
What you're trying to do is invoke operator<< using a lambda that returns an ostream& as the right-hand argument, but you're not passing the ostream& argument to the lambda itself.
os << w2(os,c.h_) is syntactically valid, but will not compile because there is no operator<<(ostream&, ostream&) definition.
What you can do is simply invoke the lambda without streaming it:
friend ostream& operator<<(ostream&os, const Clock& c) {
auto w2 = [](ostream&os, int f) -> ostream& {
return os << setw(2) << setfill( '0' ) << f; };
w2(os, c.h_);
os <<':';
w2(os, c.m_);
os << ':';
return w2(os, c.s_);
}
wandbox example
If you want to achieve your desired syntax, you will need a little more work. Here's a possible solution:
template <typename TF>
struct streamable : TF
{
streamable(TF&& f) : TF{std::move(f)} { }
};
template <typename TF>
auto& operator<<(ostream& os, const streamable<TF>& s)
{
s(os); return os;
}
template <typename TF>
auto make_streamable_impl(TF f)
{
return streamable<TF>(std::move(f));
}
template <typename TF>
auto make_streamable(TF f)
{
return [&](auto&& x) mutable
{
return make_streamable_impl([&](ostream& os) -> auto&
{
f(os, x);
return os;
});
};
}
Usage:
friend ostream& operator<<(ostream&os, const Clock& c) {
auto w2 = make_streamable([](ostream&os, int f) -> ostream& {
return os << setw(2) << setfill( '0' ) << f; });
return os << w2(c.h_) <<':'<<w2(c.m_)<<':'<<w2(c.s_);
}
wandbox example
Note that a real implementation should probably perfectly-capture the arguments into the lambdas.
This compiles:
friend ostream& operator<<(ostream&os, const Clock& c) {
auto w2 = [](ostream&os, int f) -> ostream& {
return os << setw(2) << setfill( '0' ) << f; };
return w2( os, c.h_ );
}

overloading << operator on enums gives runtime error

Like in this code :
#include <iostream>
enum class A {
a,
b
};
std::ostream& operator<<(std::ostream& os, A val)
{
return os << val;
}
int main() {
auto a = A::a;
std::cout << a;
return 0;
}
When I did not provide std::ostream& operator<<(std::ostream& os, A val) the program didn't compile because A::a didn't have any function to go with <<. But now when I've already provided it, it produces garbage in my terminal and on ideone, it produces a runtime error (time limit exceeded).
std::ostream& operator<<(std::ostream& os, A val) {
return os << val;
}
This causes infinite recursion. Remember that os << val is really seen to the compiler operator<<(os,val) in this instance. What you want to do is print the underlying value of the enum. Fortunately, there is a type_trait that allows you to expose the underlying type of the enum and then you can cast the parameter to that type and print it.
#include <iostream>
#include <type_traits>
enum class A {
a, b
};
std::ostream& operator<<(std::ostream& os, A val) {
return os << static_cast<std::underlying_type<A>::type>(val);
}
int main() {
auto a = A::a;
std::cout << a;
}
std::ostream& operator<<(std::ostream& os, A val)
{
return os << val; // Calls the function again.
// Results in infinite recursion.
}
Try
std::ostream& operator<<(std::ostream& os, A val)
{
return os << static_cast<int>(val);
}

Invoking specialized ostream operator

I have the following code...
#include <sstream>
enum class eTag
{
A,
B,
C
};
template<eTag I> std::ostream& operator<< (std::ostream& str, int i)
{
return str; // do nothing
}
template<> std::ostream& operator<< <eTag::A>(std::ostream& str, int i)
{
return str << "A:" << i; // specialize for eTag::A
}
template<> std::ostream& operator<< <eTag::B>(std::ostream& str, int i)
{
return str << "B:" << i; // specialize for eTag::B
}
template<> std::ostream& operator<< <eTag::C>(std::ostream& str, int i)
{
return str << "C:" << i; // specialize for eTag::C
}
int main()
{
std::ostringstream s;
// s << <eTag::A>(42) << std::endl;
return 0;
}
This compiles. But as you can see from the commented line in main(), I'm struggling with how to actually invoke a specialization of the ostream operator.
Quick answer:
operator<< <eTag::A>(std::cout,42);
I think you're much better off with implementing your own template-class manipulator that friends ostream& operator<<(ostream&), and keeps the state as a member variable (initialized via a constructor). See here (except for the template-part)
operator<<<eTag::A>(std::cout, 42) << std::endl;
(You can add a space between operator<< and the template argument list if you want. Doesn't make a difference.)
This is pretty nasty. Usually we don't write operators that require explicit template arguments. Better to do something like this:
inline std::ostream& operator<<(std::ostream& os, eTag x) {
if (x == eTag::A) {
return os << "A:";
} else if (x == eTag::B) {
return os << "B:";
} else if (x == eTag::C) {
return os << "C:";
} else {
throw std::range_error("Out of range value for eTag");
}
}
Then:
std::cout << eTag::A << 42 << std::endl;
A good compiler will be able to inline this, so your code will be as efficient as if you had just typed
std::cout << "A:" << 42 << std::endl;

Multiple output operators?

is it possible to define multiple output operators for an enum? I want to use this
std::ostream& operator<< (std::ostream& os, my_enum e);
operator to (1) print a human readable text and to (2) convert it to some code for storing in a database.
Thanks
Create wrappers which will return some object instead of ostream& which will handle printing. In your case it will object for printing humand-readable value and object for printing database code. Here's rough example which prints human-readable form and integer form. ostream_enum_wrapper_human class with its operator << is used for printing human-readable form, class ostream_enum_wrapper_int with its << is used for printing integer code. To switch from ostream& to wrapper, operator << (ostream&, wrappertag) is used, which wraps ostream object inside of wrapper and returns wrapped object. So next << operator is called on wrapper object, not on ostream&, and wrapper class knows how to print value.
#include <iostream>
using namespace std;
class ostream_enum_wrapper_human
{
public:
ostream& out;
ostream_enum_wrapper_human(std::ostream& _out) : out(_out){}
};
class ostream_enum_wrapper_int
{
public:
std::ostream& out;
ostream_enum_wrapper_int(std::ostream& _out) : out(_out){}
};
enum T{zero,one,two};
struct human_readable{} HumanReadable;
ostream_enum_wrapper_human operator << (ostream& out, human_readable){
return ostream_enum_wrapper_human(out);
}
struct print_int{} PrintInt;
ostream_enum_wrapper_int operator << (ostream& out, print_int){
return ostream_enum_wrapper_int(out);
}
ostream& operator << (ostream_enum_wrapper_human out, T t)
{
switch(t) {
case zero: out.out << "zero"; break;
case one: out.out << "one"; break;
case two: out.out << "two"; break;
}
return out.out;
}
ostream& operator << (ostream_enum_wrapper_int out, T t)
{
return out.out << static_cast<int>(t);
}
int main()
{
cout << HumanReadable << zero << PrintInt << zero << HumanReadable << two;
}
prints zero0two
You may take advantage of overloading by the first argument.
//For human-readable output
std::ostream& operator<< (std::ostream& os, my_enum e);
//For database; note the absence VVV of & sign here
std::ostream& operator<< (databasefmt fmt, my_enum e)
{
std::ostream& os = fmt.stream;
// Write data to os
// ...
return os;
}
struct databasefmt{
std::ostream& stream;
databasefmt(std::ostream & s) : stream(s) {};
};
Then write stream modifier that converts the stream to wrapping databasefmt class, so that next output to that modified stream would be database output for you enum. The printing code would look like this:
output_stream << "DATA: "<< database_format << my_enum::Value << "END OF DATA" ;
// Type: std::ostream | databasefmt | std::ostream |
and the wrapper like this:
//Variable is needed to avoid confusing parentheses in output operators
struct databasefmt_converter_t {} database_format;
// we can't return reference, so we just return fairly small instance of wrapper
databasefmt operator<< (std::ostream& os, databasefmt_converter_t const&)
{ return databasefmt(os); }
Sure why not? You would have to create an ostream derived class which implements writing to the database, much the same as ofstream writes to a file. The devil is in the details.
The preferred way is to use std::ios_base::xalloc and then std::ios_base::iword:
int getxalloc()
{
static const int ix = std::ios_base::xalloc();
return ix;
}
enum my_enum
{
zero,
one,
two,
};
std::ostream& operator<<(std::ostream& os, my_enum e)
{
switch (os.iword(getxalloc())
{
default:
case 0:
os << (int)e;
break;
case 1:
switch (e)
{
case zero:
os << "zero";
break;
case one:
os << "one";
break;
case two:
os << "two";
break;
default:
os << "unknown";
break;
}
break;
}
return os;
}
int main()
{
my_enum e = one;
std::cout.iword(getxalloc()) = 0;
std::cout << e << "\n"; // will output "1"
std::cout.iword(getxalloc()) = 1;
std::cout << e << "\n"; // will output "one"
}
After that you could add some fancy manipulator of your own, instead of using std::ios_base::iword directly. Like this:
inline std::ios_base& format_my_enum_as_int(std::ios_base& ib)
{
ib.iword(getxalloc()) = 0;
return ib;
}
inline std::ios_base& format_my_enum_as_string(std::ios_base& ib)
{
ib.iword(getxalloc()) = 1;
return ib;
}
int main()
{
my_enum e = one;
std::cout << format_my_enum_as_int << e << "\n"; // will output "1"
std::cout << format_my_enum_as_string << e << "\n"; // will output "one"
}
This solution is far from perfect; but there is no really nice one to your problem.
class MyClass {...};
namespace xml
{
std::ostream& operator << (std::ostream& os, MyClass& c);
}
namespace text
{
std::ostream& operator << (std::ostream& os, MyClass& c);
}
As you can see I put the stream operators in namespaces. As a result I have to include the namespace into the current one. This is simply done with a simple using declaration.
using namespace xml;
The trick is to put the using declaration in the smalest scope possible.