简体   繁体   中英

Using ostream_iterator and operator << to display a vector of pointers

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM