нет, кроме посещения для STD :: вариант - PullRequest
0 голосов
/ 27 декабря 2018

Для некоторых стандартных библиотечных классов доступ к частям их содержимого может законно завершаться ошибкой.Обычно у вас есть выбор между каким-то потенциально выбрасывающим методом, помеченным noexcept.Последнее избавляет от проверки предварительных условий, поэтому, если вы хотите взять на себя ответственность, вы можете это сделать.Это может быть использовано в тех случаях, когда использование исключений не разрешено, или при устранении узкого места производительности.

Пример 1: std::vector доступ к элементу:

std::vector<int> vec;
vec.at(n) // throws std::out_of_range
vec[n] // potentially UB, thus your own responsibility

Пример2: std::optional доступ:

std::optional<int> optn;
optn.value() // throws std::bad_optional_access
*optn // potentially UB, thus your own responsibility

Теперь перейдем к std::variant.Непосредственный доступ к альтернативе в некоторой степени следует этой схеме:

std::variant<std::string, int> var;
std::get<int>(var) // potentially throwing std::bad_variant_access
*std::get_if<int>(&var) // potentially UB, thus your own responsibility

Но на этот раз подпись меняется, мы должны ввести * и &.Недостатком этого является то, что мы не получаем семантику автоматического перемещения.Еще одна вещь, которую нужно помнить ...

Но становится еще хуже, если вы посмотрите на std::visit(Visitor&& vis, Variants&&... vars).Для него нет альтернативы noexcept, хотя он выбрасывает

, если какой-либо вариант в vars valueless_by_exception .

Это означает, что посещениеварианты, которые вы не можете выбрать, чтобы взять на себя ответственность, и если у вас нет выбора и вы должны избегать исключений, вы вообще не можете посетить std::variants со стандартными инструментами!(кроме ужасного обходного пути switch на variant::index())

Для меня это выглядит довольно плохим упущением дизайна ... или есть причина для этого?И если я прав насчет надзора, есть ли инициатива исправить это в стандарте?

1 Ответ

0 голосов
/ 27 декабря 2018

Это означает, что при посещении вариантов вы не можете взять на себя ответственность

Конечно, вы можете.Состояние «без значения по исключению» может иметь место только , если вы присваиваете значение или добавляете его в существующее значение variant.Кроме того, по определению, это может произойти только в том случае, если во время этих процессов на самом деле выдается исключение.Это не то состояние, которое когда-либо случается со случайным variant.

Если вы берете на себя ответственность за то, что вы либо никогда не устанавливаете / не присваиваете вариант, либо что используемые вами типы никогда не выбрасывают в этих обстоятельствахили что вы реагируете на любые исключения из этого таким образом, что с variant, который спровоцировал его, не разговаривают (т. е. если выдается bad_alloc, ваше приложение не перехватывает его; оно просто выключается;), тогда вам не нужно заботиться об этой возможности.

В принципе, если вы уже кодируете код, чтобы избежать исключений, статус не noexcept visitне имеет значения.Ни один variant никогда не попадет в «бесполезное за исключением», если не будет сгенерировано исключение.

...