I have a template like this:
template<typename T>
struct foo {
T m_t;
foo(T t) : m_t(t) {}
};
The problem is that I want to support both small/regular types and huge types (like matrices) for T
. Do you recommend I write the constructor initializer list like this
foo (T t) : m_t(std::move(t)) {}
and require that the type T
always support move construction, even for smaller types? Are there better ways?
and require that the type T always support move construction, even for smaller types?
Any type that is copy constructable is also move constructable. Moving in those cases simply calls the copy constructor. Thus, there's no reason not to use m_t(std::move(t))
.
An alternative is to use references instead:
foo (T const& t) : m_t(t) {}
foo (T&& t) : m_t(std::move(t)) {}
This has the benefit of only involving one construction rather than two.
Yes, using the move has no disadvantage in that situation. All copyable objects are automatically moveable, so it doesn't matter. In fact, some recommend to always move variables when possible, even integers.
As an alternative, you may consider to use perfect forwarding, as described in this answer:
template <typename T2>
foo(T2&& t) : m_t(std::forward<T2>(t)) {}
If you know that T
defines a fast move constructor, it should not matter. Otherwise, providing a constructor foo(const T&)
is recommended to avoid unnecessary copies.
Perfect forwarding is only one technique to achieve that. The solution of Pubby to write out the constructor foo(const T&)
and foo(T&&)
is, of course, also fine. The results are the same, it is mostly a matter of style.
You also asked about small integer types. In theory, passing them by reference is slower than copying them, but the compiler should be able to optimize it to a copy, anyway. I don't think it will make a difference.
So, better optimize for the worst case where T
can be huge and does not provide a fast move constructor. Passing by reference is best for that situation and should not be a bad choice in general, either.
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