Рассмотрим следующий пример, в котором мы анализируем данные и передаем результат следующей функции:
Content Parse(const std::string& data);
void Process(Content content);
int main()
{
auto data = ReadData();
Process(Parse(data));
}
Теперь давайте изменим код, используя std::optional
обработать неудачный шаг разбора:
optional<Content> Parse(const std::string& data);
void Process(Content content);
int main()
{
auto data = ReadData();
auto content = Parse(data);
if (content)
Process(move(*content));
}
Это действительно, чтобы перейти от optional<T>::value()
? Если это нормально для std::optional
это действительно для boost::optional
также?
Это действительно, чтобы перейти от optional<T>::value()
так как он возвращает изменчивую ссылку, и перемещение не разрушает объект. Если optional
экземпляр не занято, value()
бросит bad_optional_access
исключение (§20.6.4.5).
Вы явно проверяете, включена ли опция:
if (content)
Process(move(*content));
Но вы не используете член value()
чтобы получить доступ к основному T
, Обратите внимание, что value()
выполняет внутреннюю проверку перед возвратом действительного T&
, В отличие от operator*
который имеет предварительное условие что optional
экземпляр должен быть занят. Это небольшая разница, но вы используете правильную идиому:
if (o)
f(*o)
в отличие от
if (o) // redundant check
f(o.value())
В Boost ситуация немного отличается: во-первых, не существует функции-члена, вызываемой value()
это обеспечивает проверенный доступ. (A bad_optional_access
исключение просто не существует). Член get()
это просто псевдоним для operator*
и всегда полагается на пользователя, проверяющего, что optional
экземпляр занят.
Других решений пока нет …