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.)
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.
No, you can't. You have to use two versions. You can combine them as @NathanOliver suggested but you still need two versions.
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.
Because the standard prohibits binding rvalues to non-const lvalue ref. It's the same problem as in
const int& x = 1; // OK
int& y = 2; // error
It seems that the standard is trying to protect you from the accidental modifications of temporaries. Unfortunately I can't really give you deeper explanation then that. But you can read this:
Why not non-const reference to temporary objects?
How come a non-const reference cannot bind to a temporary object?
Of course at the end &&
was invented exactly to allow that. So I guess its more like a historical reason?
上一篇: 前/后缀增量的左值和右值
下一篇: 无法使函数接受右值和左值引用