[g++] баг или стандарт?
В частности, он мог скипнуть твой конструктор от AutoPtr<Q>. Получить при этом отсутствие конструктора копирования и сгенерить его самому.
P.S. Не знаю, что сказал бы стандарт, но компилятор vc7 ведет себя точно также.
ошибка должна происходить при инстанциировании шаблона
Я тоже так думаю. Но почему я тогда получаю такое странное поведение? Вот что непонятно. Грубо говоря, кто неправ?
Имхо это неправильно. Он должен сказать что я дурак и код у меня дурацкий, а не пропускать его молча.
После того как я убрал const, все заработало
Тут?
inline AutoPtr( const AutoPtr< Q >& ap ) ...
А что, если const-а нету, то это тоже считается конструктором копий?!
Ну это не есть конструктор копий... Просто я его так назвал, так как сигнатуры схожи... А вообще говоря AutoPtr невозможно СКОПИРОВАТЬ, на то он и AutoPtr
-----------------------
inline AutoPtr( const AutoPtr< Q >& ap ) throw :
d_p( ap.release )
{
printf( "2\n" );
}
------------------------
Этот конструктор создает объект AutoPtr и не кидает исключений/ошибок компиляции когда объекту типа P можно присвоить объект типа Q
Такой же(ОЧЕНЬ похожий) пример обсуждался в Страуструпе в разделе про шаблоны.
ЗЫ: Исходя из названия класса - зачем создавать велосипед, почему не воспользоваться стандартной библиотекой boost? (Без обид - если автор хочет этого, я не против)
PS: Использовать буст ради одного шаблона? Ну ну.
Sensible operation of template function overloading in C++ relies on the SFINAE (substitution-failure-is-not-an-error) principle: if an invalid argument or return type is formed during the instantiation of a function template, the instantiation is removed from the overload resolution set instead of causing a compilation error. The following example, demonstrates why this is important:
int negate(int i) { return -i; }
template <class F>
typename F::result_type negate(const F& f) { return -f; }
Suppose the compiler encounters the call negate(1). The first definition is obviously a better match, but the compiler must nevertheless consider (and instantiate the prototypes) of both definitions to find this out. Instantiating the latter definition with F as int would result in:
int::result_type negate(const int&);
where the return type is invalid. If this was an error, adding an unrelated function template (that was never called) could break otherwise valid code. Due to the SFINAE principle the above example is not, however, erroneous. The latter definition of negate is simply removed from the overload resolution set.
Думаю, что для конструкторов действует сходная логика. Ботать стандарт ломает :-)
Твой конструктор не является конструктором копии с точки зрения компилятора C++ даже если Q == T. Так поэтому создается конструктор по умолчанию.
C точки зрения компилятора первая версия очень даже является конструктором копий. Без const - не является. Мне кажется верным именно первое объяснение. Спасибо за цитату
Оставить комментарий
mirt1971
Сегодня ночью столкнулся с такой штукой: есть у меня шаблон класса AutoPtr:Очевидно что конструктор копий некорректен, он не должен даже компилироваться(передается константная ссылка, и у нее вызывается неконстантный метод release.
Как вы думаете что происходит во время компиляции/выполнения такой функции?
Вместо того чтобы сказать что у меня неправильный конструктор, g++ создает конструктор по умолчанию и использует его. После того как я убрал const, все заработало. Так вот, хотелось бы понять, это баг или поведение, требуемое стандартом?