Supposedly there is an error in the last call to ::max() in the code below, something about returning a temporary local value but I only see returning a pointer by value which is not temporary... I see a call to the 3 parameter ::max function with the parameters passed by reference, then this function calls the 2 parameter ::max that receives pointers to char by value, supposedly creating a temporary local value that is destroyed and leaves a hanging reference. I don't see that. Does somebody see a problem with this set of overloaded functions when called with pointers to char?
// maximum of two values of any type (call-by-reference)
template<typename T>
T const& max (T const& a, T const& b)
{
return b < a ? a : b;
}
// maximum of two C-strings (call-by-value)
charconst* max (charconst* a, charconst* b)
{
return std::strcmp(b,a) < 0 ? a : b;
}
// maximum of three values of any type (call-by-reference)
template<typename T>
T const& max (T const& a, T const& b, T const& c)
{
return max (max(a,b), c); // error if max(a,b) uses call-by-value
}
int main ()
{
auto m1 = ::max(7, 42, 68); // OK
charconst* s1 = "frederic";
charconst* s2 = "anica";
charconst* s3 = "lucas";
auto m2 = ::max(s1, s2, s3); // run-time ERROR -- don't see it??
}
#include <iostream>
#include <cstdlib>
#include <cstring>
charconst* max (charconst* a, charconst* b)
{
return std::strcmp(b,a) < 0 ? a : b;
}
charconst* const& max (charconst* const& a, charconst* const& b, charconst* const& c)
{
charconst* max_ret = max(a,b);
return max (max_ret, c); // error if max(a,b) uses call-by-value
}
int main ()
{
charconst* s1 = "frederic";
charconst* s2 = "anica";
charconst* s3 = "lucas";
::max(s1, s2, s3); // run-time ERROR -- don't see it??
}
It's potentially returning that local value -- max_ret -- by reference.
That is what appears to be the issue to me, but hopefully someone else can confirm.
Edit: Fixed copypaste error
Edit 2: You get similar warning if you do:
1 2 3 4 5
charconst* const& max (charconst* const& a, charconst* const& b, charconst* const& c)
{
charconst* max_ret = max(a,b);
return max_ret;
}
The point is that the return value is a reference, which is a synonym for another object. In this case there's a chance that the other object will go out of scope when the function returns.
max_ret is destroyed when control leaves the function's scope.
1 2
// f() always returns a dangling reference
int& f() { int x = 0; return x; }
but copy elision guarantees that the return value will be copied (or actually pasted) directly into m2 before the temporary expires, right?
The variant of copy elision that applies when saying return local_variable is called Named Return Value Optimization, or NRVO. It only occurs when the function's return type and local_variable are the same class type (it is a reference type in the OP), ignoring const and volatile.