I've got the following implementation of the c++ concept move_constructible
from cppreference
template<typename _Tp>
concept move_constructible =
constructible_from<_Tp, _Tp> &&
convertible_to<_Tp, _Tp>;
I don't get why this works. I presume any type can be converted to itself, so the second requirement is pointless (God, I must be very wrong about something). Also, for the first requirement I would have expected something like constructible_from<_Tp, _Tp&&>
to check if the type can be constructed from rvalue-ref (thus, moved).
Please explain how this implementation works.
Most traits/concepts automatically add &&
to the types of "source" arguments (things that are passed to functions, as in std::is_invocable
, or constructed from, as in std::is_constructible
).
I.e. constructible_from<A, B>
is equivalent to constructible_from<A, B &&>
(&&
is automatically added to the second argument, but not to the first), and convertible_to<A, B>
is equivalent to convertible_to<A &&, B>
.
Note that if a type already includes &
, adding &&
to it has no effect. So, while T
and T &&
are equivalent here, T &
is not.
This can be inferred from those traits/concepts being defined in terms of std::declval<T>()
, which returns T &&
.
For the reason why std::declval<T &>()
returns T &
, see reference collapsing.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With