Здесь, кажется, есть несколько вопросов.
1.Безопасно ли обрабатывать std::optional
в теле функции noexcept
?
Да, если тип T
, заключенный в std::optional
, не является копируемым.
В этом коде:
if (ox)
return {ox.value() * 2};
, поскольку вы проверяете перед вызовом std::optional::value()
, исключение никогда не будет выдано.При этом, поскольку вы уже уверены, что ox.has_value()
, лучше использовать operator*
:
if (ox)
return {*ox * 2};
Таким образом, компилятору не нужно будет генерировать проверку предусловия и *Оператор 1022 * (в простых случаях компилятор может оптимизировать это на основе if (ox)
, но зачем заставлять компилятор работать больше).
2.Это эффективный метод для возврата вычислений?Может ли это избежать некоторого раздувания исключений?
Предположительно, под "раздуванием исключений" вы подразумеваете издержки двоичного размера из всего кода обработки исключений, который должен сгенерировать компилятор.Если по какой-либо причине вы действительно заботитесь об этом, тогда да - техника std::optional
может избежать этого раздува за счет увеличения накладных расходов, когда не возникает ошибок.
Это компромисс, который вы должны принять с этимстиль обработки ошибок (std::optional
, std::error_code
, результат и т. д.).Вы соглашаетесь с постоянными накладными расходами на успех, чтобы получать постоянные накладные расходы на неудачу.Исключения, с другой стороны, приводят только к накладным расходам (недетерминированным во времени и пространстве) при сбое.
В этом конкретном случае вам, вероятно, было бы лучше не загрязнять простую функцию, которая в противном случае не может завершиться с ошибкойобработки.Вместо этого делайте это звонящему.Ведь вызывающий может уже знать, что значение существует.
3.Может ли это вызвать какие-либо проблемы?
Основной проблемой здесь является отсутствие какой-либо информации об ошибке.std::optional
не может передать причину сбоя операции.В обычном приложении это может не быть проблемой, но как только вы начнете составлять более сложные операции, проблемы с отслеживанием причины сбоя станут очевидными.
Даже в этом коде есть несколько состояний ошибкиэто может быть полезно для надлежащего сообщения: ошибки ввода-вывода и ошибки синтаксического анализа.И затем среди ошибок синтаксического анализа:
- ввод может быть недопустимым числом;
- число может превышать диапазон
int
.
Предполагая, что вы в конечном итоге не используете исключения, рассмотрите возможность использования чего-то вроде предложенной std :: Ожидается или Библиотека результатов .
Я бы не рекомендовал просто использовать std::variant
(по крайней мере, не оборачивая его), поскольку он не передает намерения обработки ошибок.Также не поддерживается удержание void
.