Подтвердить что ты не робот

Как перейти от std:: optional <T>

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

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?

4b9b3361

Ответ 1

Действителен переход от 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.