I was reading cpp-next where this min
template is presented as an example of how verbose C++ code can be compared to python code
template
Returning by reference might sometimes be a feature, not a bug. We'll return to this later. First a recap of the basics:
int x; int y;
x // this is an lvalue
y // lvalue also
x+y // not an lvalue - you couldn't do (x+y) = 3
x
The last line shows that a ?:
can often be an lvalue. i.e. You can do (x
(1<3?6:8)=0
as you can't do 6=0
or 8=0
. So it's just an rvalue in that case.
Inside min, x and y are the names of the function parameters and hence are lvalues. decltype(x
int&
. (I found this other cpp-Next article useful also.)
So why might this be a problem? Well, if the return type of min
is a reference, then it will return a reference to one of x
or y
, the function parameters. The question now is, were x and y references themselves?
Consider this use case:
int m = 5; int n = 10;
min(m,n) = 0; // do you want this to work?
We have a decision to make. Maybe we want min to return references, if the arguments to min
were references. I guess it's somewhat a matter of taste. If you rigorous want to return only non-references, this is easy to enforce with std::remove_reference
around the decltype(x
If you use the original example definition of min
, along with non-reference types for x or y, then min will return a reference to the local values among its parameters. This is bad as the references will be invalid and the behaviour undefined. For example, this would be bad:
int p = min(5,8); // reading from a now-invalid reference.
So, we have to go through a variety of use-cases and decide what behaviour we want:
// Desired behaviour
int m = 5;
int n = 10;
min(3,7); // return by value. i.e. return an int
min(m,n); // return an int& which maps to either m or n
min(3,n); // return by value
min(foo(), bar()) // what makes sense here?
Can we all agree on what behaviour we would want from such a min
? And then, how do we implement it?