In the following simple example, why can't ref2
be bound to the result of min(x,y+1)
?
#include <cstdio>
template< typename T > const T& min(const T& a, const T& b){ return a < b ? a : b ; }
int main(){
int x = 10, y = 2;
const int& ref = min(x,y); //OK
const int& ref2 = min(x,y+1); //NOT OK, WHY?
return ref2; // Compiles to return 0
}
live example - produces:
main:
xor eax, eax
ret
EDIT: Below example better described a situation, I think.
#include <stdio.h>
template< typename T >
constexpr T const& min( T const& a, T const& b ) { return a < b ? a : b ; }
constexpr int x = 10;
constexpr int y = 2;
constexpr int const& ref = min(x,y); // OK
constexpr int const& ref2 = min(x,y+1); // Compiler Error
int main()
{
return 0;
}
live example produces:
<source>:14:38: error: '<anonymous>' is not a constant expression
constexpr int const& ref2 = min(x,y+1);
^
Compiler returned: 1
It's by design. In a nutshell, only the named reference to which the temporary is bound directly will extend its lifetime.
[class.temporary]
5 There are three contexts in which temporaries are destroyed at a different point than the end of the full-expression. [...]
6 The third context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except:
- A temporary object bound to a reference parameter in a function call persists until the completion of the full-expression containing the call.
- The lifetime of a temporary bound to the returned value in a function return statement is not extended; the temporary is destroyed at the end of the full-expression in the return statement.
- [...]
You didn't bind directly to ref2
, and you even pass it via a return statement. The standard explicitly says it won't extend the lifetime. In part to make certain optimizations possible. But ultimately, because keeping track of which temporary should be extended when a reference is passed in and out of functions is intractable in general.
Since compilers may optimize aggressively on the assumption that your program exhibits no undefined behavior, you see a possible manifestation of that. Accessing a value outside its lifetime is undefined, this is what return ref2;
does, and since the behavior is undefined, simply returning zero is a valid behavior to exhibit. No contract is broken by the compiler.