Bsh
Bsh

Reputation: 368

How to use the overloaded "operator<<" properly?

There is a template class in c++:

#include <iostream>
#include <vector>

using std::ostream;
using std::vector;

template<typename T>
class Business {
public:

    // default constructor
    Business() {
        customers.push_back(0);
    }

    // value constructor
    Business(vector<T> vec) {

        for (int i = 0; i < vec.size(); ++i)
            customers.push_back(vec[i]);
    }

    T getInfo(int i) const {
        if (i < 0 ) return 0;
        else return customers[i];
    }

    friend ostream &operator<<(ostream &os, const Business<T> &b) {

        std::string message = "";
        for (int i=0 ; i<b.customers.size() ; ++i) {
            message += b.getInfo(i) + " ";
        }
        return os << message;
    }

private:
    vector<T> customers;
};

But I receive the following error about the operator<< body:

error: invalid operands to binary expression: message += b.getInfo(i) + " ";

After receiving that error, I changed the errorprone line of code to:

message += b.getInfo(i)

But then the error was:

error: no viable overloaded '+=': message += b.getInfo(i)

Edit: There is a main class in which I have:

Business<Merchant<95>> bu({45, 87, 95, 23});
std::cout << bu << endl;

where Merchant<95> is a another template class.

The error I receive is follows by:

in instantiation of member function 'operator<<' requested here: cout << bu << endl;

I wonder how to fix it?

Thanks.

Upvotes: 1

Views: 94

Answers (3)

Bsh
Bsh

Reputation: 368

Thank you all people who spent time to solve the question, I just needed to change the body of the for loop inside friend ostream &operator<<. Therefore, the correct way is as follows:

friend ostream &operator<<(ostream &os, const Business<T> &b) {
        for (int i=0 ; i<b.customers.size() ; ++i) {
            os << b.getInfo(i);
        }
        return os;
}

Upvotes: 2

Ghii Velte
Ghii Velte

Reputation: 125

The error you are receiving is related to the type (class) that you are instantiating the template on -- Merchant in your main example --, not the template class Bussiness itself.

Make sure that you have defined a function within Merchant to convert it to a string, or even char const*, and your code will compile.

Upvotes: 1

rranjik
rranjik

Reputation: 792

I could not provide a fix without looking at your Merchant class template. I can tell what the issue is,

When you instantiate a Business with Merchant, the T in your class template is replaced with a Merchant. The compiler stamps out a Business<Merchant> that will have a member function like the following, among other things,

   Merchant getInfo(int i) const {
        if (i < 0 ) return 0;
        else return customers[i];
    }

As you can see, getInfo returns a Merchent (the returned T is replaced with Merchent). Now this is where the problem creeps in. Consider the following now,

        std::string message = "";
        for (int i=0 ; i<b.customers.size() ; ++i) {
            message += b.getInfo(i) + " ";
        }

In message += b.getInfo(i);, message is of type string and b.getInfo(i) returns a Merchant as we saw before. The compiler doesn't know how to convert a Merchant to string to add it to message. Thus is throws a no match for 'operator+='.

A fix would to be tell the compiler how to convert a Merchant to a string explicit. This requires defining operator std::string() in Merchant.

It might look like so,

Merchant<T>{
    ...
    public:
         operator std::string() const { 
             return to_string(MerchantID)+... }
    ...
};

This depends on your Merchant and the primitive types that is has within. See operator std::string() const?.

Upvotes: 1

Related Questions