Reputation: 13713
Thinking about (x|r|l|pr|gl)values, the following question came to my mind:
Consider the following two variable declarations:
X x = ...;
and
X&& x = ...;
and assume the ...
do not deliver an xvalue.
Can anybody think of code not using decltype
in which this makes a difference? In both cases, (x)
will by an lvalue of type X
, won't it?
Upvotes: 12
Views: 555
Reputation: 137310
Template non-type arguments cannot refer to a temporary. Thus, given
struct X {};
X purr() { return {}; }
X x1 = purr();
X&& x2 = purr();
template<X&> class woof {};
we have
woof<x1> w1; // OK
woof<x2> w2; // Error
If ...
isn't limited to a prvalue of type X
, then slicing is a less obscure way to make the two non-equivalent. Given:
struct X { virtual ~X() = default; };
struct Y : X {};
Y meow() { return {}; }
Then:
X x1 = meow(); // slices
X&& x2 = meow(); // doesn't slice
Thus:
dynamic_cast<Y&>(x1); // throws std::bad_cast
dynamic_cast<Y&>(x2); // OK
Upvotes: 5
Reputation: 217145
Maybe artificial example, but with
struct X
{
X() = default;
X(const X&) = delete;
X operator =(const X&) = delete;
X(X&&) = delete;
X operator =(X&&) = delete;
};
X makeX() {return {};}
following compiles
X&& x = makeX();
whereas following doesn't
X x = makeX();
Upvotes: 7