Вот пример игрушка :
struct problem {
problem()=default;
problem(problem&&)=default;
problem(problem&)=delete;
};
template<class T>
struct bob {
T t;
bob()=default;
bob(bob&&)=default;
bob(bob const&)=default;
};
int main() {
problem p;
problem p2 = std::move(p);
bob<problem> b;
bob<problem> b2 = std::move(b);
}
bob<problem>
не удается скомпилировать, потому что bob(bob const&)=default
выдает ошибку при взаимодействии с problem(problem&)=delete
.
* 1010 Возможно, стандартное «следует» выдает ошибку, когда определяет, что он не может реализовать
bob(bob const&)
, и обрабатывает
=default
как
=delete
(как если бы у нас было
problem(problem const&)=delete
), но стандартная формулировка - это не ' не будет безупречным в этом угловом корпусе углового корпуса. И этот угол углового случая будет достаточно странным и причудливым, поэтому я не уверен, что общее правило, которое заставляет его переводить
=default
в
=delete
, будет правильным!
Исправление, если мы problem(problem const&)=delete
(ну, к packaged_task
) будет намного чище, чем все, что мы делаем для =default
правил ctor.
Теперь стандартное погружение:
Во-первых, очевидно, что у неявно объявленного конструктора копирования bob<problem>
выше будет подпись bob(bob&)
в [class.ctor] . Я даже не буду цитировать стандарт для этого, потому что ленивый.
Мы go и явно по умолчанию bob(bob const&)
копируем ctor, который отличается в сигнатуре от того, который был бы неявно объявлен.
Существуют правила, касающиеся явно дефолтных функций, и их конфликт с сигнатурами приведен в 11.4.2.
В явно дефолтных функциях [dcl.fct.def.default] 11.4.2 / 2
2 Тип T1
явно дефолтной функции F
может отличаться от типа T2
, который был бы, если бы он был неявно объявлен, следующим образом:
- ( 2.1) T1
и T2
могут иметь разные ref-квалификаторы; и
- (2.2), если T2
имеет параметр типа const C&
, соответствующий параметр T1
может иметь тип C&
.
Если T1
отличается из T2
любым другим способом, затем:
- (2.3), если F
является оператором присваивания, а тип возвращаемого значения T1
отличается от типа возвращаемого значения T2
или T1
тип параметра не является ссылкой, программа некорректна;
- (2.4) в противном случае, если F
явно указано по умолчанию в первом объявлении, оно определяется как удаленное;
- (2.5) в противном случае программа некорректно сформирована.
По умолчанию установлено значение T1
, которое содержит const&
, а не &
, поэтому (2.2) не применить.
Мое чтение действительно понято (2.4); тип bob(bob const&)
отличается от неявно объявленного bob(bob&)
недопустимым образом; но первое объявление default
ed, поэтому оно должно быть delete
d.
Я смотрю на черновую версию n4713 ; возможно, в более старой версии этого пункта не было.