Assume I have some templated class
template <typename T>
struct Dummy {
// ...
};
And I want to overload a function 'foo' such that it accepts a lvalue
or rvalue reference of it. I can do this using some IsDummy
trait
as follows:
template <typename A>
std::enable_if<IsDummy<A>::value, void>
foo(A &&dummy)
{
// ....
}
IIRC in some C++11 draft it was legal that
template <typename A>
foo(Dummy<A> &&dummy)
{
// ....
}
would accept both, lvalue- and value- references.
Now my questions:
a) Is it correct that it was allowed in some draft?
b) Why was this feature/bug removed? I think I read somewhere that it was due to a conflict with "concepts".
However, I can't find appropriate references for this any more. Does somebody have a better memory or bookmarks?
a) Is it correct that it was allowed in some draft?
Yes, it was allowed in what is known as "rvalue references 1.0" (see N2118).
b) Why was this feature/bug removed? I think I read somewhere that it was due to a conflict with "concepts".
It was removed because binding an rvalue reference to an lvalue could lead to a violation of the "Principle of Type-safe Overloading" in the presence of Concepts:
Every function must be type-safe in isolation, without regard to how it has been overloaded.
For example, if we define the following overloads:
template< CopyConstructible T > void f( T const & t ); // #1
template< MoveConstructible T > void f( T && t ); // #2
Then calling f
with a copyable lvalue would select #1. However, if T is a non-copyable type (e.g. std::unique_ptr
) then #1 is not a viable overload so the compiler must select #2, possibly stealing resources from an lvalue without warning.
See "rvalue references 2.0" (N2844) for more details.