I'm trying to display a vector of pointers on objects using ostream_iterator
and the operator <<
. Thus, I override the operator <<
. The problem that I always get the vector elements address. How do I make the iterator to print the actual values? Do I need to specialize it?
class A {
private:
double x;
long y;
public:
A(long xx, double yy) :x(xx), y(yy){};
~A();
void Display();
};
template<typename T>
std::ostream &operator <<(std::ostream &os, const std::vector<T> &v) {
using namespace std;
copy(v.begin(), v.end(), ostream_iterator<T>(os, "\n"));
return os;
}
int main()
{
std::vector<A*> aVect;
FillA(aVect);
cout << accountVect;
return 0;
}
//
output
00657990
006579D0
00657A48
You could write an operator<<
overload for A*
, but it'd be slightly nicer to dereference the pointer first, like:
template<typename T>
std::ostream &operator <<(std::ostream &os, const std::vector<T *> &v) {
std::transform(v.begin(), v.end(),
ostream_iterator<T>(os, "\n"),
[](T const *ptr) -> T const& { return *ptr; }
);
return os;
}
and then write the usual operator<<
overload for A
.
Note - as @WhozCraig mentioned in comments, your existing code isn't printing the vector element's address , it's printing the vector element as you asked, and that element is an address. The simplest possible fix would be to just use a vector<A>
in the first place, if you can.
However, I've assumed you need to keep the vector<A*>
and want to print the dereferenced A
objects.
Also, I've stuck with your original template, but it's not entirely clear whether a non-templated operator<<(ostream&, vector<A*> const &)
would be cleaner.
I've a bit modified your code to work:
#include <functional>
class A {
public:
A(){ x = 5; y = 5;}
A(long xx, double yy) :x(xx), y(yy){};
~A();
void Display() {
std::cout << "X: " << x << " | Y: " << y << std::endl;
}
double x; // made this public just not to create an accessor
long y;
};
template<typename T>
std::ostream &operator <<(std::ostream &os, const std::vector<T*> &v) {
std::transform(v.begin(), v.end(), std::ostream_iterator<decltype(T::x)>(os, "\n"), [](const T* t){return t->x;});
// or use A::Display() method with std::bind
std::for_each(v.begin(), v.end(), std::bind(&A::Display, std::placeholders::_1));
// or with std::mem_fn
std::for_each(v.begin(), v.end(), std::mem_fn(&A::Display));
return os;
}
int main()
{
std::vector<A*> aVect = {new A, new A, new A};
std::cout << aVect;
return 0;
}
So the first problem is that you need to specialize properly:
std::ostream &operator <<(std::ostream &os, const std::vector<T*> &v) {
instead of
std::ostream &operator <<(std::ostream &os, const std::vector<T> &v) {
This is because you have array of pointers but your current specialization works for non-pointer objects of vector.
Next, I've modified your std::copy
call because will not work ever until you provide a operator<<
overload for your class A
. So, I've changed it to std::transform
to be able to output your values.
UPD: also, here is a way to use your A::Display()
method with std::for_each
algorithm with use std::bind
or std::mem_fn
functional objects.
Considering that std::ostream_iterator
itself uses operator<<
for the output, you can solve this easily by doing another overload:
std::ostream& operator<<(std::ostream& os, A const* a)
{
// Some output of `a` here
return os;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.