Svalorzen
Svalorzen

Reputation: 5608

C++ does not compile by uncommenting move operator

I have the following code:

template <typename T>
struct X {
    X() : x(5) {}

    template <template <typename> class S>
    X(const S<T> & y) : x(y.x) {}

    // Uncomment and it does not compile anymore
    // X(X&& z) : x(z.x) {}

    T x;
};

int main ()
{
    X<int> y;
    auto x = y;
    return 0;
}

Could you explain why it does not compile once the specified code is uncommented?

Upvotes: 3

Views: 61

Answers (2)

max66
max66

Reputation: 66210

Humam Helfawi got the point.

I try to complete his answer.

Svalorzen: look at this code

#include <iostream>

template <typename T>
struct X {
    X() : x(5) {}

    template <template <typename> class S>
    X (const S<T> & y) : x(y.x)
     { std::cout << "templated constructor" << std::endl; }

    X (const X<T> & y) : x(y.x)
     { std::cout << "copy constructor" << std::endl; }

    T x;
};

int main ()
{
    X<int> y;
    auto x = y;
    return 0;
}

The output is "copy constructor".

When the compiler find a matching templated function and a matching plain (no templated) function, choose the plain as more specific.

Now delete the definition of the copy contructor

#include <iostream>

template <typename T>
struct X {
    X() : x(5) {}

    template <template <typename> class S>
    X (const S<T> & y) : x(y.x)
     { std::cout << "templated constructor" << std::endl; }

    T x;
};

int main ()
{
    X<int> y;
    auto x = y;
    return 0;
}

and you get your example without the move constructor and with the cout ("templated constructor") added.

You can see that the output is empty.

That's because the compiler choose the copy contructor that, as default version, is implicitly present.

When you add the move constructor, you incidentally mark as deleted the copy constructor. But the copy constructor is ever present (even as marked as deleted) and the compiler consider it. So, when the compiler try to implement "x = y", match your your templated constructor, match the copy constructor, choose the copy constructor (more specific), see that is deleted and give error.

When you add

X (const X<T> &) = default;

you permit the compiler to use the copy constructor.

p.s.: sorry for my bad English.

Upvotes: 2

Humam Helfawi
Humam Helfawi

Reputation: 20274

Copy constructor is implicitly declared as deleted because you declared a move constructor.

Add a default (or user defined) copy constructor and it would compile fine:

X(const X<T>&)=default;

Upvotes: 3

Related Questions