具有自定义返回类型和"错误"返回条件的函数?

Mik*_*nen 20 c++

我有一个返回自定义类结构的函数,但是如何处理我希望通知用户函数失败的情况,如返回false.

我的函数看起来像这样:

Cell CSV::Find(std::string segment) {
  Cell result;
  // Search code here.
  return result;
}
Run Code Online (Sandbox Code Playgroud)

因此,当成功时,它会返回正确的结果,但是当它失败时我该如何处理?

我想在Cell中添加一个布尔方法来检查什么Cell.data是空的(Cell.IsEmpty()).但我是否以过于复杂的方式思考这个问题?

小智 41

有三种一般方法:

  • 使用例外.这就是Bathsheba的回答.
  • 返回std::optional<Cell>(或其他一些可能或可能不包含实际的类型Cell).
  • 返回bool,并添加一个Cell &参数.

其中哪一个最好取决于您打算如何使用此功能.如果主要用例传递有效段,则一定要使用例外.

如果该函数的部分设计是可以用来判断一个段是否有效,则异常是不合适的,我的首选是std::optional<Cell>.这可能不适用于您的标准库实现(这是C++ 17的功能); 如果没有,boost::optional<Cell>可能是有用的(如Richard Hodges的回答中提到的).

在评论中,而不是std::optional<Cell>用户建议expected<Cell, error>(不是标准的C++,而是针对未来的标准提出,并且在此std之前可以在命名空间之外实现).如果有多种可能的原因,这可能是一个很好的选择,可以添加一些指示,说明为什么找不到传入Cellsegment参数.

我包括的第三个选项主要是为了完整性.我不推荐它.它是其他语言中流行且通常很好的模式.

  • @ Mikko-PenttiEinariEronen OS级操作通常设计为可以从任何语言调用.一种流行语言C没有例外或任何"可选"类型,因此第三种选择是唯一保留的语言. (5认同)

Ric*_*ges 7

这个函数是一个查询,它可以有效地找不到单元格,或者它是一个必要条件,期望找到单元格?

如果是前者,则返回一个可选的(或可空的指针)单元格.

如果是后者,如果没有找到则抛出异常.

前任的:

boost::optional<Cell> CSV::Find(std::string segment) {
  boost::optional<Cell> result;
  // Search code here.
  return result;
}
Run Code Online (Sandbox Code Playgroud)

后者:就像你拥有它一样.

当然还有基于c ++ 17变体的方法:

#include <variant>
#include <string>

struct CellNotFound {};
struct Cell {};

using CellFindResult = std::variant<CellNotFound, Cell>;


CellFindResult Find(std::string segment) {
  CellFindResult result { CellNotFound {} };

  // Search code here.
  return result;
}

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

void cellsAndStuff()
{
    std::visit(overloaded
    {
        [&](CellNotFound)
        {
            // the not-found code
        },
        [&](Cell c)
        {
            // code on cell found
        }
    }, Find("foo"));
}
Run Code Online (Sandbox Code Playgroud)