The code below illustrated my concern:
#include <iostream>
struct O
{
~O()
{
std::cout << "~O()\n";
}
};
struct wrapper
{
O const& val;
~wrapper()
{
std::cout << "~wrapper()\n";
}
};
struct wrapperEx // with explicit ctor
{
O const& val;
explicit wrapperEx(O const& val)
: val(val)
{}
~wrapperEx()
{
std::cout << "~wrapperEx()\n";
}
};
template<class T>
T&& f(T&& t)
{
return std::forward<T>(t);
}
int main()
{
std::cout << "case 1-----------\n";
{
auto&& a = wrapper{O()};
std::cout << "end-scope\n";
}
std::cout << "case 2-----------\n";
{
auto a = wrapper{O()};
std::cout << "end-scope\n";
}
std::cout << "case 3-----------\n";
{
auto&& a = wrapper{f(O())};
std::cout << "end-scope\n";
}
std::cout << "case Ex-----------\n";
{
auto&& a = wrapperEx{O()};
std::cout << "end-scope\n";
}
return 0;
}
See it live here.
It's said that auto&&
will extend the life-time of the temporary object, but I can't find the standard words on this rule, at least not in N3690.
The most relevant may be section 12.2.5 about temporary object, but not exactly what I'm looking for.
So, would auto&& life-time extension rule apply to all the temporary objects involved in the expression, or only the final result?
More specific, is a.val
guaranteed to be valid (non-dangling) before we reach the end-of-scope in case 1?
Edit: I updated the example to show more cases (3 & Ex).
You'll see that only in case 1 the lifetime of O is extended.