Как перейти от std :: необязательный & lt; T & gt;

Рассмотрим следующий пример, в котором мы анализируем данные и передаем результат следующей функции:

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 также?

15

Решение

Это действительно, чтобы перейти от 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 экземпляр занят.

11

Другие решения

Других решений пока нет …