2016-07-16 7 views
3

У меня есть следующий код:C++ не компилирует раскомментировав перемещения оператора

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; 
} 

Не могли бы вы объяснить, почему он не компилируется после того, как указанный код раскомментирована?

+1

Рассмотрите возможность размещения ошибки с кодом. – zneak

ответ

2

Хумама Helfawi получил точку.

Я стараюсь завершить его ответ.

Svalorzen: посмотрите на этот код

#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; 
} 

Выход "конструктор копирования".

Когда компилятор найдет подходящую шаблонную функцию и соответствующую обычную (без шаблонов) функцию, выберите равнину как более конкретную.

Теперь удалите определение копии застройщика

#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; 
} 

и вы получите ваш пример без конструктора перемещения и с соиЬ («шаблонный конструктор») добавил.

Вы можете видеть, что выход пуст.

Это потому, что компилятор выбирает контр-копию, который по умолчанию является неявным.

Когда вы добавляете конструктор перемещения, вы случайно отмечаете как удаленный конструктор копирования. Но конструктор копирования всегда присутствует (даже как отмечено как удаленный), и компилятор его рассматривает. Итак, когда компилятор попытается реализовать «x = y», сопоставьте свой шаблонный конструктор, сопоставьте конструктор копирования, выберите конструктор копирования (более конкретный), увидите, что он удален и дает ошибку.

При добавлении

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

вы позволяете компилятору использовать конструктор копирования.

p.s .: извините за мой плохой английский.

3

Конструктор копирования неявно объявлен как удаленный, поскольку вы объявили конструктор перемещения.

Добавить по умолчанию (или определенный пользователем) конструктор копирования и он будет компилироваться:

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

Mmhh .. Я предполагаю, что специфицированный конструктор шаблона, который я объявлял, не считается конструктором копирования? Или это неправильно? – Svalorzen

+1

@Svalorzen Вы правы, конструктор шаблонов никогда не является конструктором копирования. –

+0

честно, я не понял, что это. Тем не менее, это не похоже на конструктор копирования .. он принимает тип шаблона, который не нужен 'X' –