Consider a simple class
template< typename T > class Wrapper { public:
What designers should use to be effective?
Prior to C ++ 0x, there would be a constructor that accepts either:
- const reference (
T const& ) - if type T is heavy, - or value (
T ) - if type T is light.
Determining whether type T “heavy” or “light” is not easy.
It can be assumed that only built-in types (ints / floats / ...) are "light". But this is not entirely correct, since our own Wrapper<int> should most likely also be considered "light."
Libraries, such as boost::call_traits , provide some means to overcome this difficulty by allowing the creator type to mark the type as "light" (by providing proper call_traits specialization). Otherwise, it will be considered as "heavy." Seems acceptable.
But C ++ 0x makes it worse. Because now you have an rvalue ( T&& ) link that allows you to efficiently accept (some) "heavy" objects.
And because of this, now you have to choose among:
- just const reference (
T const& ) - if the type T is "heavy" and does not support the semantics of movement (because either not - like with large PODs), or none of them were written, and you have no influence on this) , - both const reference (
T const& ) and rvalue reference ( T&& ) - if the type T "heavy" and supports the semantics of movement, - just value (
T ) - if the type T "light" or "heavy", but supports moving semantics (even if the copy is made, it does not require use, because otherwise we would have to copy from T const& anyway ...) .
However, it is not easy to say which types are "heavy" and which are "light" (as before). But now you also cannot determine whether type T supports transfer semantics or not (or you?).
This becomes even more annoying if you wrap more than one value, as the number of possible constructor overloads grows exponentially.
Is there any solution to this problem?
I’m at least talking about some template designers for sending arguments (flawlessly redirecting) the arguments, but I was not sure if this would work as desired. And also it would allow us to provide values of various types that would simply be sent to the T constructor. This can be considered a sign, but not required.