Подтвердить что ты не робот

Явные конструкторы по умолчанию в С++ 17

В С++ 17 пустые типы тегов в стандартной библиотеке теперь имеют конструкторы по умолчанию, которые помечены explicit, а также = default. Например, std::piecewise_construct_t теперь определяется как

struct piecewise_construct_t { explicit piecewise_construct_t() = default; };

Мой вопрос просто, в чем причина этого изменения с С++ 14? Что означает явно установленный по умолчанию явный конструктор по умолчанию (!) Для пустого класса?

(Чтобы не быть помеченным как обман: этот вопрос с 2010 года спрашивает о целях явных конструкторов по умолчанию, но это был pre-С++ 11 и давным-давно, так что вещи, скорее всего, изменились. Этот вопрос является более поздним, но ответ, похоже, предполагает, что агрегатная инициализация будет выполняться независимо от наличия конструктора по умолчанию, поэтому мне любопытно, почему это изменение в последнем стандарте.)

4b9b3361

Ответ 1

Обоснование изменения библиотеки находится в LWG 2510 "Типы тегов не должны быть DefaultConstructible" :

std::experimental::optional, по определенным причинам, указывает свой тип nullopt, чтобы он не был DefaultConstructible. Он не делает этого для своего типа тега in_place_t, и ни один из стандартных не подходит для любого из его типов тегов. Это оказывается очень неудачным, рассмотрим следующее:

#include <memory>
#include <array>

void f(std::array<int, 1>, int) {} // #1
void f(std::allocator_arg_t, int) {} // #2

int main()
{
  f({}, 666); // #3
}

Вызов в # 3 неоднозначен. Еще хуже то, что если перегрузка № 1 удалена, вызов работает просто отлично. Весь смысл типа тега заключается в том, что он либо должен упоминаться в вызове, либо должен быть переадресованным аргументом, поэтому возможность создания типа тега вроде этого не имеет смысла.

Проблема LWG развивалась бок о бок с CWG 1518 "Явные конструкторы по умолчанию и инициализация списка копий" , которая имеет полезный фон.