Search code examples
c++operator-overloadingc++14autoostream

Using ostream overloading on pointers to objects


So, I have a struct Bike, which looks like this

struct Bike {
    std::string brand;
    std::string model;
    bool is_reserved;

    friend std::ostream& operator<<(std::ostream out, const Bike& b);
};
std::ostream& operator<<(std::ostream out, const Bike& b) {
    return out 
        << "| Brand: " << b.brand << '\n'
        << "| Model: " << b.model << '\n';
}

And another class BikeRentalService, which has a std::vector<Bike*> called bikes_m. This class also has a method print_available_bikes(), which is supposed to iterate over said std::vector<Bike*> and print each Bike by using the overloaded operator<< shown above. This method looks like that:

void BikeRentalService::print_available_bikes(std::ostream& out) {
    if (bikes_m.empty()) {
        out << "| None" << '\n';
    }
    else {
        for (auto bike : bikes_m) {
            if (!bike->is_reserved) {
                out << bike;
            }
        }
    }
}

The problem is that using this function just prints out the addresses of those Bike objects. Dereferencing the objects before using out << does not work either, Visual Studio says it can't reference std::basic_ostream because it is a "deleted function". Writing the for loop as (auto *bike : bikes_m) does not change anything.


Solution

  • The rigth way to overload the ostream operator is as follows:

    struct Bike {
        std::string brand;
        std::string model;
        bool is_reserved;
    
        friend std::ostream& operator<<(std::ostream& out, const Bike& b); // <- note passing out by reference
    };
    std::ostream& operator<<(std::ostream& out, const Bike& b) {
        return out 
            << "| Brand: " << b.brand << '\n'
            << "| Model: " << b.model << '\n';
    }
    

    Also, as noted by @KyleKnoepfel you should change out << bike; to out << *bike; too.