2015-09-12 5 views
5

У меня есть класс шаблона, у которого есть конструктор копии шаблона. Проблема в том, что когда я создаю экземпляр этого класса, используя другой экземпляр этого класса с тем же типом шаблона, конструктор экземпляра шаблона не вызывается. Почему это не соответствует? Вот фрагмент кода:C++ template copy constructor on template class

#include <iostream> 

template <typename T> 
class MyTemplateClass 
{ 
    public: 
     MyTemplateClass() 
     { 
      std::cout << "default constructor" << std::endl; 
     } 

     /* 
     MyTemplateClass(const MyTemplateClass<T>& other) 
     { 
      std::cout << "copy constructor" << std::endl; 
     } 
     */ 

     template <typename U> 
     MyTemplateClass(const MyTemplateClass<U>& other) 
     { 
      std::cout << "template copy constructor" << std::endl; 
     } 
}; 

int main() 
{ 
    MyTemplateClass<int> instance; 
    MyTemplateClass<int> instance2(instance); 
    return EXIT_SUCCESS; 
} 

Выход

default constructor 

Но если я явно написать конструктор копирования по умолчанию (раскомментировав его), то выход становится

default constructor 
copy constructor 

Я действительно не понимаю. Я тестировал его с помощью своего локального компилятора (clang-500.2.79) и с this one (gcc 4.9.2) и получил тот же результат.

+5

Шаблон никогда не был (!) Конструктором копирования! –

+5

Конструктор копирования никогда не является шаблоном. –

+0

Существует неявно объявленный конструктор копирования, который является предпочтительным при разрешении перегрузки. –

ответ

2

Конструктор копирования имеет форму X(X&) или (X const&) и будет предоставлен вам компилятором, если вы не объявили его самостоятельно (или несколько других условий, которые здесь не актуальны). Вы не так неявно мы следующий набор кандидатов:

MyTemplateClass(const MyTemplateClass&); 
template <typename U> MyTemplateClass(const MyTemplateClass<U>&); 

Оба являются жизнеспособными для

MyTemplateClass<int> instance2(instance); 

Оба принимают те же точные аргументы. Проблема заключается не в том, что ваш шаблон конструктора копий не соответствует. Проблема заключается в том, что неявный конструктор копирования не является шаблоном функции, а не-шаблоны предпочтительнее специализированных шаблонов, когда дело доходит до разрешения перегрузки. Из [over.match.best], опуская несвязанные пункты пули:

Учитывая эти определения, жизнеспособная функция F1 определяется, чтобы быть лучше, чем функция другой жизнеспособной функции F2, если для всех аргументов я, ICS я (F1), не хуже, чем последовательность преобразования ICS я (F2), а затем
- [...]
- F1 не шаблон функции специализации и F2 является функцией специализации шаблона, или, если нет, то
- [...]

Именно поэтому он называет ваш неявный (а затем, ваш явный) экземпляр экземпляра над вашим шаблоном конструктора.

+0

Почему не-шаблоны предпочитают специализированные шаблоны, когда дело доходит до разрешения перегрузки? Это потому, что в большинстве случаев это лучшая стратегия выбора? – syntagma

+1

@REACHUS Прямой ответ заключается в том, что это правило (добавленная стандартная цитата). Общее правило - выбрать наиболее определенную функцию. Не-шаблон более конкретный, чем шаблон. – Barry

+0

ОК, моя ошибка заключалась в том, чтобы думать, что никакой конструктор копий не будет создан. – Jairard

2

Когда у вас нет конструктора копирования в вашем коде, компилятор будет его неявным образом генерировать. Поэтому, когда эта линия выполнена:

MyTemplateClass<int> instance2(instance); 

копия конструктор является выполняется, хотя, очевидно, не твое. Я думаю, что шаблоны не имеют к этому никакого отношения.

Подробнее об этом здесь: Implicitly-defined copy constructor

-1

Я думаю REACHUS прав, компилятор генерирует копию-конструктор по умолчанию (как это было бы с классом нешаблонном тоже) и предпочитая это над шаблоном, как это более специализированный. Вы должны сделать свой «обычный» экземпляр-конструктор частным или лучше использовать ключевое слово C deleted 11 «deleted», чтобы пометить функцию как непригодную для использования. EDIT: Это не компилируется, извините, я не смог проверить его в то время.

+0

Оба эти предложения сделают код не скомпилированным - не предпочитайте называть шаблон конструктора. – Barry

+0

@Barry Почему вы думаете, что в этом случае не стоит объявлять конструктор удаленной копии? – syntagma

+0

@REACHUS Это сделает класс не подлежащим копированию. Я не считаю, что это цель OP. – Barry