Does this template ctor hide move ctor?
class A {
public:
template<typename T>
A(T &&t);
// move would be as this:
/*
A(A &&a);
*/
};
And how in this situation should I implement move ctor then? Should it be with default syntax A (A &&)
or a template specialization?
In general, the compiler should generate move members if you have no user-declared copy members nor destructor. = default and = delete counts as user-declared. If you declare one move member (e.g. move constructor), the other will not be implicitly generated. The compiler will never implicitly delete move members.
Move constructor moves the resources in the heap, i.e., unlike copy constructors which copy the data of the existing object and assigning it to the new object move constructor just makes the pointer of the declared object to point to the data of temporary object and nulls out the pointer of the temporary objects.
When we create our own copy constructor, we pass an object by reference and we generally pass it as a const reference. One reason for passing const reference is, we should use const in C++ wherever possible so that objects are not accidentally modified.
Implicitly-defined move constructor For non-union class types (class and struct), the move constructor performs full member-wise move of the object's bases and non-static members, in their initialization order, using direct initialization with an xvalue argument.
According to the standard (draft)
[class.copy]
3 A non-template constructor for class X is a move constructor if its first parameter is of type X&&, const X&&, volatile X&&, or const volatile X&&, and either there are no other parameters or else all other parameters have default arguments (8.3.6). [ Example: Y::Y(Y&&) is a move constructor.
Only non-template constructors can be move constructors. Same applies to copy constructors†. Therefore the implicit move constructor is generated.
You implement the move constructor in the usual way. Specialization won't work because the implicit non-template move constructor is preferred by the overload resolution.
† If the argument type does not match exactly to const T&
, however, the templated reference wins the overload resolution. This can easily happen as can be seen in Praveen's example.
The accepted answer is incorrect. While it is true that: template <typename T> A(T &&t) { }
is not a move constructor, you already knew that. The compiler will implicitly declare a move constructor in this case and normal overload resolution will work as expected:
A a{2}; // calls template
A b = std::move(a); // calls move
A c{a}; // calls template
There is nothing precluding a
from being moved into c
, even though the template constructor isn't a "move" constructor.
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