I have a function which sorts two vectors with the first of them as ordering criterion. Its signature is
template<typename A, typename B>
void sort(A&& X, B&& Y)
{
..
}
The problem is that universal references would allow nonsense cases like
sort(vector<int>{ 2,1,3 }, vector<int>{ 3,1,2 });
where an rvalue will be destroyed afterwards (nonsense).
Asking explicitly for a lvalue doesn't work since
template<typename A, typename B>
void sort(A& X, B& Y) ... // (*)
sort(vector<int>{2,1,3}, vector<int>{3,1,2});
for some reason the above compiles (I thought only const lvalues were allowed to bind to rvalues and to prolong their lifetime?).
If I add const
to the lvalue reference then the function will no longer be able to modify the vectors and sort them.
My questions are:
1) Why in the example marked with // (*)
can I bind a rvalue to a lvalue that is not even const
? Why instead something like int& r = 20;
isn't allowed? What's the difference?
2) How can I solve my issue i.e. having the function accept only lvalues and not rvalue temporaries? (If it's possible, of course)
Obviously I'm allowed to use any C++ version available
The answer is: your compiler is wrong.
Check on gcc or clang or similar and you'll get something like this:
prog.cpp: In function 'int main()': prog.cpp:9:45: error: invalid initialization of non-const reference of type 'std::vector&' from an rvalue of type 'std::vector' sort(vector{2,1,3}, vector{3,1,2}); ^ prog.cpp:6:6: note: initializing argument 1 of 'void sort(A&, B&) [with A = std::vector; B = std::vector]' void sort(A& X, B& Y) { }