Пример правильно сформированного определения класса с дефолтной специальной функцией-членом, которую компилятор удаляет - PullRequest
2 голосов
/ 24 марта 2020

В стандарте C ++ 20, [dcl.fct.def.default] , явно заданные по умолчанию функции:

2 Тип T<sub>1</sub> явно специальная функция-член по умолчанию F может отличаться от типа T<sub>2</sub>, который был бы при неявном объявлении, следующим образом:

(2.1) - T<sub>1</sub> и T<sub>2</sub> могут иметь отличия ref-qualifiers;

(2.2) - T<sub>1</sub> и T<sub>2</sub> могут иметь различные спецификации исключений; и

(2.3) - если T<sub>2</sub> имеет параметр типа const C&, соответствующий параметр T<sub>1</sub> может иметь тип C&.

Если T<sub>1</sub> отличается из T<sub>2</sub> любым другим способом, тогда:

(2.4) - если F является оператором присваивания, а тип возвращаемого значения T<sub>1</sub> отличается от типа возвращаемого значения T<sub>2</sub> или T<sub>1</sub> тип параметра не является ссылкой, программа некорректна;

(2.5) - в противном случае, если F явно указано по умолчанию в первом объявлении, оно определяется как удаленное;

(2.6) - в противном случае программа некорректна

Кто-нибудь может привести пример специальной функции-члена, явно заданной по умолчанию и удаленной компилятором. Объявление функции должно быть правильно сформировано.

1 Ответ

2 голосов
/ 24 марта 2020

Пример из P0641 , откуда эта формулировка:

struct MyType {
  MyType(MyType&);  // no 'const'
};

template <typename T>
struct Wrapper {
  Wrapper(const Wrapper&) = default;
  T t;
};

Wrapper<MyType> var;  // fails to instantiate

Притворяться, что на самом деле был конструктор по умолчанию.

Это было ранее неправильно сформировано. Теперь T<sub>1</sub> (конструктор копирования Wrapper) отличается от того, чем он был бы, если бы он был неявно объявлен (было бы Wrapper(Wrapper&) per [class.copy.ctor] / 7 ) , Это не соответствует случаям в первом наборе пуль (здесь T<sub>1</sub> имеет const&, но не T<sub>2</sub>, пуля в обратном порядке), поэтому мы переходим ко второму набору пуль - и мы в итоге удаляется конструктор копирования Wrapper<MyType>.

Хорошим примером того, как это могло бы появиться в коде, является что-то вроде std::tuple (см. LWG2086 ), где до этих изменений:

struct A {
  A();
  A(A&);
};
std::tuple<A> x; // ill-formed

Теперь, это правильно, просто что tuple<A> не копируется.

...