Вариант C ++: Почему для преобразования конструктора требуется, чтобы sizeof ... (Types) отличался от нуля - PullRequest
0 голосов
/ 04 февраля 2019

Этот вопрос касается: template<class...Types> class variant:

Согласно variable.variant / 3 , экземпляр программы variant без аргументов шаблона имеет неправильную форму.

Пока все ясно.Теперь у меня есть вопрос, касающийся конструктора преобразования (template<class T> constexpr variant(T&& t) noexcept(see below)):

variable.variant / variable.ctor-16.1 говорит, что конструктор преобразования не должен участвовать в разрешении перегрузки, если только:

sizeof ... (Типы) не равен нулю

(... и некоторые другие требования, которые меня сейчас не волнуют).

MyВопрос в том, когда variant без аргументов шаблона уже делает мою программу плохо сформированной, почему все еще заботится о том, участвует ли мой конвертирующий конструктор в разрешении перегрузки или нет?

Посмотрите на MSVC и libstdc ++ -реализация variant они фактически имеют enable_if_t<sizeof...(_Types) != 0> в объявлении конструктора преобразования.Почему?

1 Ответ

0 голосов
/ 05 февраля 2019

Предложение "sizeof ... (Types) отлично от нуля" было добавлено к [variant.ctor] как часть статьи: Некоторые улучшения в выводе аргументов шаблона классаинтеграция в стандартную библиотеку для поддержки variant.

Соответствующие выдержки:

Включить поддержку вариантов

Следующий код не может скомпилировать

variant<int, double> v1(3);
variant v2 = v1;  // Ill-formed! <--THIS

Поскольку этот естественный код полезен и его сбой сбивает с толку, мы предлагаем его поддерживать.Действительно, до принятия p0510r0 запрета variant<> приведенный выше код работал, как и ожидалось, поскольку variant<> встречается в некоторых руководствах по выводам в наборе перегрузки.Поскольку не ясно, что при принятии p0510r0 учитывался вывод аргумента шаблона конструктора, мы хотели бы рассмотреть возможность разрешения variant<>, чтобы не вызывать серьезную ошибку в таких случаях.

Wording (Выделениедобавлено)
Изменить §23.7.3.1p16 [variant.ctor] следующим образом:
Примечания: Эта функция не должна участвовать в разрешении перегрузки, если sizeof...(Types) не равен нулю , если толькоis_same_v<decay_t<T>, variant> равно false, если decay_t<T> не является ни специализацией in_place_type_t, ни специализацией in_place_index_t, если is_constructible_v<Tj, T> не является true, и если выражение FUN (std :: forward (t))) (с FUN, являющимся вышеупомянутым набором мнимых функций) хорошо сформирован.

Таким образом, std::variant v2 = v1; терпит неудачу в версиях компилятора, которые не учитывают добавленное предложение (как GCC 7.1. См. DEMO ), но успешно в более поздних версиях (начиная с GCC 7.2 и далее. См. DEMO ).

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