C++11 allows a rvalue reference to be declared in global(,namespace, class) scope and to have static storage duration. What would be a good scenario for using such variables? I have made several tests and have come up with a few observations. The following piece of code will not compile (g++ 5.3)
double&& m = 3.5;
double&& s() {return m;}
testy.cpp: In function ‘double&& s()’:
testy.cpp:7:22: error: cannot bind ‘double’ lvalue to ‘double&&’ double&& s() {return l;}
This is rather counterintuitive, even thought we declared a rvalue reference it is treated as if the data is returned by value. This is, of course, a contrived example and indeed returning a rvalue reference is rare. However why does it not work? My interpretation is that by declaring the rvalue reference m with static storage duration we get a form of "universal reference", a term coined by Scott Meyers (more info here). One of the properties of a universal reference is that it can bind to both lvalues and rvalues. However unlike "universal references", which rely on reference collapse due to type substitutions, the mechanism which is involved in the resolution above is unclear to me. In fact the following code compiles without problems.
double&& m = 3.5;
int main() {
double a {4.2};
double& b = a;
m = a;
m = b;
m = 3.2;
}
Hence, as stated above, m binds to every flavor of double. However the fact that the variable has static storage duration seems to contradict the nature of rvalues, which bind to temporary object. There are few questions that arise. Why is that allowed? What scenario will make use of this property?. My first guess was that we can use that in providing template specializations which accept any "flavour" of argument, much the same way universal references do, with the exception that they are bound more strongly to the underlying type. Moreover the scope of the "static rvalue reference" seems not to matter, ie rvalues with static storage duration and "function" scope also exhibit the behavior as demonstrated below.
int main() {
static double&& a = 4.2;
double b = 3.2;
double& c = b;
a = b;
a = c;
}