Конструкторы лямбда-замыкания - PullRequest
8 голосов
/ 16 апреля 2019

cppreference показывает, что существуют разные правила для конструкторов типа лямбда-замыкания.

Конструкция по умолчанию - до C ++ 14

ClosureType () = удалить;(до C ++ 14)

Типы замыканий не являются конструируемыми по умолчанию.Типы замыкания имеют удаленный (до C ++ 14) конструктор по умолчанию (с C ++ 14).

Конструкция по умолчанию - с C ++ 14

Типы замыканий не имеют конструктора по умолчанию (начиная с C ++ 14).

Конструкция по умолчанию - начиная с C ++ 20

Если захваты не указаны, тип замыкания имеет конструктор по умолчанию по умолчанию.В противном случае он не имеет конструктора по умолчанию (включая случай, когда существует захват по умолчанию, даже если он фактически ничего не захватывает).

Оператор назначения копирования - до C ++20

Оператор назначения копирования определен как удаленный (и оператор назначения перемещения не объявлен).Типы замыканий не являются CopyAssignable.

Оператор назначения копирования - начиная с C ++ 20

Если захват не указан, тип замыкания имеетоператор назначения копии по умолчанию и оператор назначения перемещения по умолчанию.В противном случае у него есть оператор присваивания удаленной копии (в том числе и случай захвата по умолчанию, даже если он на самом деле ничего не захватывает).

В чем причина такого изменения вправила?Определил ли комитет по стандартизации некоторые недостатки в стандарте для конструкции типа лямбда-замыкания?Если да, то что это за недостатки?

1 Ответ

8 голосов
/ 16 апреля 2019

Был недостаток. Мы не могли использовать лямбды так же «на лету», как хотелось бы. C ++ 20 (с добавлением разрешения лямбды в неоцененных контекстах) делает этот код допустимым:

struct foo {
    int x, y;
};

std::map<foo, decltype([](foo const& a, foo const& b) { return a.x < a.y; })> m;

Обратите внимание, как мы определили встроенную функцию сравнения? Не нужно создавать именованный функтор (в противном случае это может быть хорошей идеей, но мы не вынуждены ). И нет необходимости разбивать объявление на две части:

// C++17
auto cmp = [](foo const& a, foo const& b) { return a.x < a.y; };
std::map<foo, decltype(cmp)> m(cmp); // And also need to pass and hold it!

Такое использование (и многие другие) было мотивирующим фактором для внесения этих изменений. В приведенном выше примере анонимный тип функторов принесет все преимущества, которые может принести именованный тип функторов. Инициализация по умолчанию и EBO среди них.

...