Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Having a function only accept non-const lvalues

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

like image 751
Dean Avatar asked Sep 22 '15 15:09

Dean


1 Answers

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) { }

like image 104
BeyelerStudios Avatar answered Oct 16 '22 15:10

BeyelerStudios