将一个std :: optional转换为另一个std :: optional

问题描述

我有一个返回可选结构的方法,如下所示:

auto getBook(const std::string &title) const -> std::optional<Book>;

我想在另一个返回可选作者的方法中调用此方法。 问题在于,在调用方法之前,实现应始终检查getBook返回的可选项是否已填写,如下所示:

auto getAuthor(const std::string &title) const -> std::optional<Author>
{
   const auto optBook = getBook(title);
   if (optBook.has_value)
      return optBook->getAuthor();
   else
      return std::nullopt;
}

是否可以用一种更简短的方式编写此代码,因此,如果填充了可选方法,则调用该方法,但是如果可选为空,则返回std::nullopt。像这样的东西(我知道这目前不起作用,但是你明白我的意思):

auto getAuthor(const std::string &title) const -> std::optional<Author>
{
   return getBook(title).getAuthor();
}

解决方法

您可以通过创建一个map函数来概括此模式,该函数采用可选的o和一个函数f,如果{{1 }}:

f(*o)

然后可以将o.has_value() == true定义为:

template <typename O,typename F>
auto map(O&& o,F&& f) -> std::optional<decltype(f(*std::forward<O>(o)))>
{
    if (!o.has_value()) 
    {
        return {std::nullopt};
    }

    return {f(*std::forward<O>(o))};
}

live example on godbolt.org


我为这类操作创建了一个库,称为scelta。使用我的库,您可以编写:

getAuthor

有关更多信息,请参见"Monadic Optional Operations"

,

boost::optionalstd::optional的基础,它的成员map就是这样做的。

例如

auto getBook(const std::string &title) const -> boost::optional<Book>;

auto getAuthor(const std::string &title) const -> boost::optional<Author>
{
   return getBook(title).map(std::mem_fn(&Book::getAuthor));
}
,

我认为,此工作需要Null Object模式,而不是std :: optional。

是的,有点类似于std :: optional,但是语义不同: 在对象上调用任何方法(如getAuthor)时,如果方法的结果有效,则返回有效对象。如果不是,则返回空对象。

不久之前,我从事类似于XML的树实现的工作,就像这样:

auto val = object.node("root").node("branch_1").node("subbranch_1").toInt();
if (val) process(val.asInt());

在node()调用的每个步骤中,如果未找到特定节点,则返回无效节点。在无效节点上调用它时,将返回无效节点。

AFAIK,目前在STL中没有实现。

编辑:为了有效地工作,您需要从某个基类派生出所有书籍,作者,章节和其他内容的所有实例,其中一个空对象将属于该基类。

编辑:这并不是所有情况下的最佳解决方案,可能太复杂了,无法在您的情况下实现。

,

我认为您可以返回所需的内容并在root函数中捕获异常,如下所示:

auto  get_size_t(const bool state)
{
 return state ? std::optional<size_t>(std::rand()) : std::nullopt;
}

auto  get_string_size_t(const bool state)
{
 return std::optional<std::string>(std::to_string(get_size_t(state).value()));
}

void  f()
try
{
 std::clog << get_string_size_t(true).value() << std::endl;
 std::clog << get_string_size_t(false).value() << std::endl;
}
catch (...)
{
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...