0

I created a class with a private vector that uses std::string as its data type.

#pragma once
#include <string>
#include <vector>
#include <iostream>

class Pokemon {
public:
//Constructor - leaving it here for reference
Pokemon(std::string name, int LVL, int HP, int ATK, int DEF, int SPATK, int SPDEF, int SPD, 
std::vector<std::string>moves, std::vector<int>PP);
//Member Functions
std::vector<std::string> getMoves();
private:
std::vector<std::string>moves;
};   

In order to retrieve information from this vector, I created a public class function titled getMoves(), which is supposed to return all of the information from that vector. Here's the function definition that I wrote in the .cpp file.

std::vector<std::string> Pokemon::getMoves() {
    return moves;
}

After attempting to print the vector which has these moves with std::cout and receiving a "no match for operator" error, I realized that I had to overload the << operator.

I have several questions on how to go about overloading the << operator so my vector will print.

  1. I'm uncertain where to declare the overload operator.Do I declare it before my class? Inside my class as a public friend function? In a different header file? Inside my main function?
  2. What type am I supposed to be overloading to print? I believe it'd be the same type as my class because the getMoves() function belongs to the Pokemon class but I'm unsure if it's that or std::vector<std::string>
    1. How do I utilize this overloaded operator within my main function? Just like a normal std::cout?

I'd appreciate any help with these questions, thank you!

2 Answers2

0

Following example will overload << operator for each vector. If you want to specify the output for your specific vector then make a wrapper struct or class.

#include <iostream> 
#include <vector>

using namespace std; 

template <typename T> 
ostream& operator<<(ostream& os, const vector<T>& v) 
{ 
    os << "[";
    for (int i = 0; i < v.size(); ++i) { 
        os << v[i]; 
        if (i != v.size() - 1) 
            os << ", "; 
    }
    os << "]\n";
    return os; 
}

Now when you want to print the vector like this:

int main() {
    vector<int> a = {0, 1, 2};
    cout << a << endl;
}

it will print the following result: [0, 1, 2]

NutCracker
  • 11,485
  • 4
  • 44
  • 68
  • Really appreciate the help! I didn't think about how useful templates would be with this. This is more efficient than overloading a single type right? – moontracer Mar 12 '19 at 15:06
  • 2
    I would recommend you to create your own wrapper class and make a dedicated overload of `<<` operator. This is always a better way I would say than overloading the whole standard `vector` class. – NutCracker Mar 12 '19 at 15:09
0
#include <iostream>
#include <vector>
#include <map>

// Helper Function to Print Test Containers (Vector and Map)
template <typename T, typename U>
std::ostream& operator<<(std::ostream& out, const std::pair<T, U>& p) {
    out << "[" << p.first << ", " << p.second << "]";
    return out;
} 

template <template <typename, typename...> class ContainerType, typename 
ValueType, typename... Args>
void print_container(const ContainerType<ValueType, Args...>& c) {
    for (const auto& v : c) {
        std::cout << v << ' ';
    }
    std::cout << '\n';
}

As NutCracker mentioned operator << overload is your best friend in almost all type of containers. In addition to his nice answer, here is a little bit extended version of templated resolution to print all type of STL containers.

Basically overloading for pair type of containers in addition to vectors. As an example. ValueType -> First or only Element in container template and Args... variadic template as rest of the elements in container (second or more elements) For pair <T,U> basic map-unordered_map you only have first and second elements to overload You can apply this technique to almost all container types. If you just want to print each Pokemon features without calling any additional function pokemon::getMoves() you can overload << for pokemon class as well it might be better to print only 1 pokemon etc.

friend to give access to private and public members

friend ostream& operator<< (ostream& os, const Pokemon& pokemonobj) {
    os << print_container(pokemonobj.getMoves());
    return os;
}
Enis Bilgin
  • 86
  • 1
  • 3