views:

154

answers:

5

I am attempting to create an overloaded unary - operator but can't get the code to compile. A cut-down version of the code is as follows:-

class frag
{
    public:

        frag myfunc  (frag oper1,
                      frag oper2);
        frag myfunc2  (frag oper1,
                      frag oper2);

        friend frag operator + (frag &oper1,
                                frag &oper2);

        frag operator - ()
        {
            frag f;
            f.element = -element;
            return f;
        }

    private:

        int element;

};

frag myfunc (frag oper1, frag oper2)
{
    return oper1 + -oper2;
}

frag myfunc2 (frag oper1, frag oper2)
{
    return oper1 + oper2;
}

frag operator+ (frag &oper1, frag &oper2)
{
    frag innerfrag;
    innerfrag.element = oper1.element + oper2.element;
    return innerfrag;
}

The compiler reports...

/home/brian/Desktop/frag.hpp: In function ‘frag myfunc(frag, frag)’:
/home/brian/Desktop/frag.hpp:41: error: no match for ‘operator+’ in ‘oper1 + oper2.frag::operator-()’
/home/brian/Desktop/frag.hpp:16: note: candidates are: frag operator+(frag&, frag&)

Could anyone suggest what I need to be doing here? Thanks.

+2  A: 

You don't have an operator+ that can operate on temporaries. Temporaries cannot be passed as non-const reference.

Change the signature of your operator+ to:

frag operator + (const frag &oper1, const frag &oper2);
Joe Gauterin
+6  A: 

const-correctness

This has to be

 frag operator+ (const frag &oper1, const frag &oper2);

or else the operands can't be temporaries, such as the return value of operator-

And unary minus should rather be:

frag operator - () const;

since it shouldn't modify the operand.

UncleBens
A: 

The answer has already been given (const arguments), but
I'd like to mention that Visual C++ 9 (VS-2008) would
indeed compile the above without warning.

Regards

rbo

rubber boots
A: 

Thank you for your help, gentlemen.

Brian Hooper
+1  A: 

Though your question has already been answered reasonably well, I think it's worth mentioning another point about your code. Right now, you have the following declarations:

class frag
{
    public:

        frag myfunc  (frag oper1,
                      frag oper2);
        frag myfunc2  (frag oper1,
                      frag oper2);

... and you have the following functions:

frag myfunc (frag oper1, frag oper2)
{
    return oper1 + -oper2;
}

frag myfunc2 (frag oper1, frag oper2)
{
    return oper1 + oper2;
}

I'd guess that you intended these two functions to implement the member functions you declared in frag -- but they don't. Instead, you have two member functions that are declared by never defined, and these two are global functions that happen to have similar names. For them to be the member functions you declared, you need to change the declaration to something like:

frag frag::myfunc(frag oper1, frag oper2) { 
    return oper1 + -oper2;
}

frag frag::myfunc2(frag oper1, frag oper2) { 
    return oper1 + oper2;
}

On the other hand, these don't really make any sense that way either -- in particular, as member functions, they'll normally be invoked as something like: a.myfunc(b,c); They're both really written like global functions though -- as member functions, they'd normally take only one parameter, and use this as the first parameter:

frag frag::myfunc1(frag oper) { 
    return *this + -oper;
}
frag frag::myfunc2(frag oper) { 
    return *this + oper;
}

Of course, this may just be an accidental side effect from trying to reduce the original code to a minimum necessary for posting. If so, please feel free to disregard this whole "answer"....

Jerry Coffin
I think you are right about it being a result of my creating a minimal criminal, as this doesn't appear in my substantive version, but thank you for mentioning it anyway.
Brian Hooper