2013-02-27 4 views
3

Выполняя некоторые ошибки, я наткнулся на следующее поведение инициализации, которое кажется мне странным: при инициализации для существующих конструкторов, похоже, были случаи, когда шаблоны для установки конструкторов игнорируются. Рассмотрим, например, следующую программу:Инициализация игнорирует шаблоны конструктора

#include <iostream> 

template<class T> 
struct A { 
A() {}; 
template<class S> 
A(const A<S>& a) {std::cout << "constructor template used for A" << std::endl;}; 
}; 

template<class T> 
struct B{ 
B() {}; 
B(const B<int>& b) {std::cout << "constructor used for B" << std::endl;}; 
}; 

int main() { 
A<int> a; 
B<int> b; 
A<int> aa = a; 
B<int> bb = b; 
A<double> aaa = a; 
} 

Для меня это производит вывод

constructor used for B 
constructor template used for A 

это означает, что он не использует конструктор в третьей строке основной. Почему нет? Есть ли причина? Или где-то мой синтаксис? Шаблон, похоже, работает, так как он успешно используется в последней строке.

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

Прошу прощения, если мой вопрос отключен, я не программист, я не носитель языка, и это мой первый вопрос, пожалуйста, простите меня.

+0

В строке 3 используется конструктор копирования, а не конструктор по умолчанию, за которым следует назначение. –

+0

Когда вы спрашиваете: «Почему он делает X вместо Y», это помогает объяснить, почему вы думаете, что он должен делать Y. Для многих людей, делающих X, может быть настолько очевидно, что они никогда не думают о том, что Y может произойти. – PlasmaHH

ответ

4

компилятор обеспечивает неявно объявленную без шаблона конструктор копирования с подписью, эквивалентной

A(const A& a); 

потому конструктор шаблона не рассматривается как определенный пользователем конструктор копирования, то есть конструктор копирования должен быть без шаблона.

Неявно объявленный конструктор копирования является лучшим совпадением в разрешении перегрузки, чем версия шаблона, и является тем, который вызывается при копировании конструкции A<T> из A<T>. Это можно проиллюстрировать с помощью простого примера, с определяемым пользователем A(const A&):

#include <iostream> 

template<class T> 
struct A 
{ 
A() {}; 

A(const A& a) { 
    std::cout << "copy constructor used for A" << std::endl; 
} 

template<class S> 
A(const A<S>& a) { 
    std::cout << "constructor template used for A" << std::endl; 
} 
}; 

int main() 
{ 
    A<int> ai; 
    A<double> ad = ai;/calls template conversion contructor 
    A<int> ai2 = ai; // calls copy constructor A(const A&); 
} 
+1

Это объяснение может применяться к любой функции, но я думаю, что это не входит в суть этого конкретного случая: почему компилятор автоматически создает независимый конструктор копирования, который может быть сгенерирован из шаблонного конструктора. – Gorpik

+0

Ну, похоже, что OP не согласен, это нормально для меня :) – Gorpik

+1

@Gorpik вы правы, я не объяснил это. Я добавил пару строк, чтобы (надеюсь) уточнить. – juanchopanza

4

в соответствии с пунктом 12.8/7 C++ 11 стандарта на:

Если определение класса не явно объявлять copy, один объявлен неявно.

Кроме того, в соответствии с пунктом 12.8/2:

без шаблона конструктор для класса X является конструктор копирования, если первый параметр имеет тип X &, сопзЬ Х &, летучее X & или const volatile X &, либо других параметров нет, либо все остальные параметры имеют аргументы по умолчанию (8.3.6).

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

A<int> aa = a; 

Это объясняет, почему вы не видите соответствующий вывод.

+0

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

+0

@ user2115777: Нет проблем, но ничто не заставляет вас принять первый ответ, который вы получаете, вы можете изменить свое мнение в любое время :-) Однако это не означает, что вы должны принять это: тот, который вы приняли, является правильным и хорошо. –

+0

Я попытался принять оба ... поэтому я знаю, что могу передумать. Остается вопрос, почему имеет смысл не допускать использования шаблонов в качестве конструкторов копирования (см. Обсуждение в принятом ответе). Если вам известно ... – user2115777

Смежные вопросы