Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does template constructor with universal reference hide move construtor?

Tags:

c++

c++11

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?

like image 893
Victor Polevoy Avatar asked Jan 22 '16 08:01

Victor Polevoy


People also ask

Does compiler create move constructor?

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.

What is the difference between a move constructor and a copy constructor?

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.

Why does copy constructor accept the objects by reference and not by value?

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.

What does implicit move constructor do?

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.


2 Answers

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.

like image 91
eerorika Avatar answered Nov 11 '22 10:11

eerorika


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.

like image 29
user5825406 Avatar answered Nov 11 '22 12:11

user5825406