The Welder
The Welder

Reputation: 1072

Operator overloading problems

I have the friends in a class definition obviously and to make it clearer, have removed the implementation code etc...

class Ref
{
    public:
        Ref(char* s, size_t l) : _s(s), _l(l) {}
    private:
        char* _s;
        size_t _l;
};

class foo
{
    public:
        friend stringstream& operator>>(std::stringstream& s, uint8_t& v) { return s; }
        friend stringstream& operator>>(std::stringstream& s, const Ref& r) { return s; }
    private:
        std::stringstream ss;
        void example(void)
        {
            char b[256];
            Ref r(b, sizeof(b));
            uint8_t i;

            ss >> i >> r;    <------ Why do I get an error here?
            ss >> r >> i;    <------ But this one seems to compile fine.
        }
};

Upvotes: 0

Views: 209

Answers (2)

Mike Seymour
Mike Seymour

Reputation: 254751

ss >> i >> r;   <-------  why do I get an error here?

You forgot to tell us what the error is, or to post the actual code that gives you the error. When I fix the obvious errors in the posted code, I get:

cannot bind ‘std::basic_istream<char>’ lvalue to ‘std::basic_istream<char>&&’

The first problem is that ss >> i won't call your overload; you can't overload the streaming operators for built-in types like uint8_t. So this will call the overload defined by the standard library, which returns a reference to istream, not stringstream. Your operator expects a reference to stringstream, so the second operator will fail.

You should follow the convention and work with a generic ostream rather than a specific stringstream:

friend std::istream& operator>>(std::istream& s, const Ref& r) { return s; }

If you actually want the operator to do anything useful, then you'll need to remove the const from the second argument.

Upvotes: 1

James Kanze
James Kanze

Reputation: 154047

Why are you overloading on std::stringstream? You should always be overloading on std::istream or std::ostream (depending on the direction). It's exceedingly rare that std::stringstream would even be used (std::istringstream or std::ostringstream would usually be more appropriate), and even if they were, operator>> will normally return a std::istream&, not a std::stringstream&.

EDIT:

With regards to why one seemed to work:

ss >> r >> i;

is

operator>>( operator>>( ss, r ), i );

You have defined an operator>> which takes a stringstream& and Ref const&, so the inner call is valid. And your operator>> returns a stringstream&, which isA std::istream, so the function operator>>( std::istream&, unsigned char ) can be called. Where as:

ss >> i >> r;

is

operator>>( operator>>( ss, i ), r );

The inner call returns an std::istream&, and there is no overloaded operator>> for std::istream&, Ref const&.

As stated above: overloaded >> should always take std::istream& as there first argument, and return an std::istream&.

Upvotes: 5

Related Questions