Search code examples
c++code-duplicationrvaluelvalue

Can't make a function accept both rvalue and lvalue references


class Vec3{

private:
    float x, y, z;

public:
    Vec3() = default;
    Vec3(const float c) {x = c; y = c; z = c;}

    static  Vec3& normalize(Vec3& v) {/* normalize */ return v;}

};

Vec3 aaa = Vec3( 1.0f);
Vec3 bbb = Vec3::normalize( Vec3( 1.0f));
Vec3 ccc = Vec3::normalize( aaa);

I wanted to write functions that take vectors as parameters, do some work on them and return them as references.

In the above code bbb will not compile because it's a non-const reference to an rvalue. I can't make it const since normalize needs to modify the object. If I make the function accept rvalue references (Vec3&& v) then ccc wont compile since aaa is an lvalue. Can I make this work without having to write two versions of normalize?

(I'm confused about rvalue vs lvalue references, I don't understand for example why a someFunc(const Vec3& v) will accept both rvalues and lvalues while the non-const version won't.)


Solution

  • You can do this with a little overhead. You wont have to write the normalizing code twice but you need to handle the returning differently as you do not want to return a reference to a rvalue.

    If you had something like

    static  Vec3& normalize(Vec3& v) {/* normalize */ return v;}
    static  Vec3 normalize(Vec3&& v) { return normalize(v);}
                                                        ^ v is a lvalue here
    

    Now you can forward the tempoary to the lvalue reference version and then return by value so that you aren't trying to refer to a object that might not exist anymore.