Reputation: 70223
The end goal is the following: I want to be able to use for_each
with operator<<
. I realized I can just use ostream_iterator
but I would like to see if it is possible without it.
Some example code so you can get an idea of what I want to do:
#include <algorithm>
#include <iostream>
#include <functional>
#include <vector>
using std::bind;
using std::ref;
using std::placeholders::_1;
using std::for_each;
using std::ostream;
using std::cout;
using std::endl;
using std::vector;
class C {
private:
int x;
public:
C() : x(0) { }
C(int x) : x(x) { }
friend ostream& operator<<(ostream& out, const C& c);
};
ostream& operator<<(ostream& out, const C& c) {
return out << c.x << endl;
}
int main() {
vector<C> v;
v.push_back(C(1));
v.push_back(C());
for_each(v.begin(), v.end(), bind(&ostream::operator<<, ref(cout), _1));
return 0;
}
A thing I have unsuccessfully tried (above):
bind(static_cast<ostream& (ostream::*)(ostream&, const C&)>(&ostream::operator<<), ref(cout), _1)
Upvotes: 0
Views: 548
Reputation: 3571
Is here any problem?
for (auto c :v) cout<<c;
or here:
for (const auto& c :v) cout<<c;
or here:
for (C const& c :v) cout<<c;
Upvotes: 1
Reputation: 157484
You're specifying the wrong operator<<
; you've specified ostream::operator<<
, but your operator<<
is free i.e. ::operator<<
.
This works in your current program:
for_each(v.begin(), v.end(), bind(&::operator<<, ref(cout), _1));
However if you add any more free operator<<
s then it will fail again, since bind
cannot decide which operator<<
is meant. In that case you would have to specify through an explicit specialization:
for_each(v.begin(), v.end(), bind<ostream&(*)(ostream&, const C&)>(&::operator<<, ref(cout), _1));
Equivalently, you could use static_cast<ostream&(*)(ostream&, const C&)>(&::operator<<)
.
The problem is that the <<
in std::cout << c
could be either a free operator or a member operator, and there's no way to know which a priori. ostream_iterator
works by generating code that allows the compiler to decide how to evaluate the expression; similarly if you use a lambda or just a range for loop.
Upvotes: 3
Reputation: 4863
You can just use a lambda, as in:
for_each(v.begin(), v.end(), [](C const& c){ cout << c; });
Personally, I prefer to use for_each
when my intention is to visit every element in the sequence.
Upvotes: 3