I was doing Leetcode when I stumbled upon this interesting technique. Here it is in short:
#include <iostream>
#include <vector>
void print(std::vector<int>& vec)
{
for (int i : vec)
{
std::cout << i << ", ";
}
}
int main()
{
print(std::vector<int>(5) = {1,2,3,4,5});
return 0;
}
We are passing seemingly rvalue to an lvalue reference, which is usually illegal, but in this specific case, it works somehow. Is there any explanation or maybe I'm missing something?
operator=
of std::vector
returns an lvalue reference and is callable on rvalue as well as lvalue object expressions (because it is just a normal non-static member function without ref-qualifier).
So std::vector<int>(5) = {1,2,3,4,5}
is permitted and is an lvalue expression that can be bound by the lvalue reference in the parameter.
Of course, that's terrible style. print
should just have a const
lvalue reference parameter and then
print({1,2,3,4,5});
would simply work.
And even if one really wants to pass a rvalue to a non-const
lvalue reference, it would be better to use a function specifically for that which clearly communicates the intent, e.g.:
template<typename T>
T& as_lvalue(T&& t) { return static_cast<T&>(t); }
//...
print(as_lvalue(std::vector<int>{1,2,3,4,5}));