О том, как выбирается альтернатива при построении варианта с одним аргументом? - PullRequest
1 голос
/ 10 января 2020

При чтении стандарта для определения конструктора [option.ctor] :

template<class T> constexpr variant(T&& t) noexcept(see below);

Я падаю на неясное ограничение:

Пусть Tj будет типом, который определяется следующим образом: построить мнимую функцию FUN(Ti) для каждого альтернативного типа Ti, для которого Ti x[] = {std​::​forward<T>(t)}; правильно сформирован для некоторой изобретенной переменной x ... он перегрузки FUN(Tj), выбранный разрешением перегрузки для выражения FUN(std​::​forward<T>(​t)), определяет альтернативу Tj, которая является типом содержимого значения после построения.

Я хотел бы понять, в чем смысл этого ограничения :

, для которого Ti x[] = {std​::​forward<T>(t)}; правильно сформировано ?

Без этого ограничения разрешение перегрузки устранило бы все перегрузки, для которых параметр не может быть инициализирован инициализацией копирования.

Насколько я вырыл, Ti x[] = {std::forward<T>(t)} должен падать на [dcl.init.aggr] / 2 :

В противном случае элемент инициализируется копией из соответствующего предложения инициализатора или инициализируется с помощью фигурной скобки или равно инициализатор соответствующего обозначенного-инициализатора-предложения. Если этот инициализатор имеет выражение-присваивание формы или = выражение-присваивания , и для преобразования выражения требуется сужающее преобразование ([dcl.init.list]), программа некорректно сформирована .

Итак, я вижу, как это ограничение удаляет из набора перегруженных мнимых функций те, которые при вызове будут включать сужающееся преобразование. Но может быть, есть еще? Я ошибаюсь? Почему инициализация массива в ограничении, а не Ti x = {std::forward<T>(t)}? Какое намерение стоит за "Ti x[] = {std​::​forward<T>(t)}; правильно сформированным"?

1 Ответ

1 голос
/ 11 января 2020

Эта формулировка добавлена ​​ P0608R3 Конструктор преобразования нормального варианта . В статье очень хорошо обобщены изменения в разделе Предлагаемое разрешение :

. В этом документе предлагается ограничить конструктор преобразования variant и оператор присваивания преобразования, чтобы предотвратить сужающие преобразования и преобразования. до bool. В этом разделе объясняется, что именно приносит это изменение.

Следовательно, единственное намерение этого изменения - предотвратить сужающие преобразования.

Почему используется массив? Редакционная заметка в разделе Формулировка отвечает на ваш вопрос:

[Редакционная заметка: Вышеприведенное использование T i x[] = {std::forward<T>(t)}; вместо T i {std::forward<T>(t)}, чтобы проверить, соответствует ли последовательность преобразования с T до T i содержит сужающее преобразование, потому что правильная форма T i {std::forward<T>(t)} может зависеть от того, T i имеет конструктор initializer_list или T i является агрегатом. Вот пример: https://godbolt.org/z/Ck5w-L - конечная нота]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...