0

I'm trying to overload the << operator to print a vector that contains elements of type Position (vector). I managed to overload the << operator for type Position, but I can't figure out how to do it for vector. Can you help?


//position.h

#ifndef POSITION_H    
#define POSITION_H
#include <iostream>    // using IO functions
using namespace std;

class Position {
private:
    int row;
    int column;

public:
    friend ostream& operator<<(ostream& os, const Position& P);
    friend ostream& operator<<(ostream& os, const vector<Position>& VP);
};

#endif

//position.cpp
#include"Position.h"
#include <iostream>    // using IO functions
#include<vector>

ostream& operator<<(ostream& os, const Position& P)
{
    os << '(' << P.row << ',' << P.column << ')' << endl;
    return os;
}
    
ostream& operator<<(ostream& os, const vector<Position>& VP)
{
    Position placeholder;

    for (int i = 0; i != VP.size(); i++)
    {
        placeholder = VP.at(i);
        cout << placeholder << endl;
    }
    return os;
}

int main() 
{
    Position C1(2, 1);
    Position C2(3, 1);
    Position C3(4, 1);

    vector<Position> cans;
    cans.push_back(C1);
    cans.push_back(C2);
    cans.push_back(C3);

    cout << cans;

    system("pause");
}

1 Answers1

0

I'm sure there's a duplicate on StackOverflow somewhere, but I cannot find it. I'm a bit surprised about this question, as I don't really see a critical issue at first sight. Did you get a compiler error or segmentation fault?

Every time you assign to Placeholder, you make a copy. This is not necessary at all: you can directly access the element at the index. As you limit the index to 0 to size(), you don't have to worry about going out-of-bounds, so don't use .at(i), which throws an exception if you go out of bounds. Just use VP[i].

Also not that std::endl flushes the buffer, which is slow. A normal enter/end-line can be achieved with the '\n' character.

Finally, using namespace std; is considered bad practice.

You have multiple options for processing the elements of the vector:

index-based for loop:

for (int i = 0; i != VP.size(); ++i) {
    os << VP[i] << '\n';
}

Iterator-based for loop

for (auto it = cbegin(VP); it != cend(VP); ++it) {
    os << *it << '\n';
}

range-based for loop

for (auto const& el : VP) {
    os << el << '\n';
}

Algorithm for(each) loop

std::for_each(cbegin(VP), cend(VP),
   [](auto const& el) { os << el << '\n'; });

Copy to ostream_iterator

std::copy(cbegin(VP), cend(VP),
    std::ostream_iterator<Position>(os, "\n"));

Note that here you could also write <decltype(VP)::value> instead of <Position> to keep it generic, but that might be overkill in this situation.

And the last two have a C++20 ranges equivalent:

std::ranges::for_each(VP,
   [](auto const& el) { os << el << '\n'; });
std::ranges::copy(VP,
   std::ostream_iterator<Position>(os, "\n"));

Note: friend ostream& operator<<(ostream& os, const vector<Position>& VP); doesn't have to be a friend of Position! It doesn't require access to the private members.

JHBonarius
  • 10,824
  • 3
  • 22
  • 41