0

在进行错误处理并仍然返回值的常用方法是使用元组。

我想知道当异常不适用时,在 C++ 中使用 std::tie 做同样的事情是否是个好主意。

喜欢

std::tie(errorcode, data) = loadData();
if(errorcode)
  ...//error handling

这样做有什么缺点(性能或其他)?我想通过返回值优化它并没有真正产生影响,但也许我错了。

我可以看到的一个潜在问题案例是在交叉编译器 API 中的使用,但这并不特定于这种使用。

我目前的做法是

errorcode = loadData(&data);
if(errorcode)
  ...//error handling

但这允许传入数据值。

错误代码本身是已经定义的,我无法更改。

编辑:我正在使用/必须使用 C++11

4

3 回答 3

2

有时输出参数非常方便。假设loadData返回std::vector<T>并在循环中调用:

std::pair<ErrorCode, std::vector<T>> loadData();

for (...) {
    ErrorCode errorcode;    
    std::vector<T> data;
    std::tie(errorcode, data) = loadData();
}

在这种情况下loadData,每次迭代都必须分配内存。但是,如果您data作为输出参数传递,则可以重用先前分配的空间:

ErrorCode loadData(std::vector<T>&);

std::vector<T> data;
for (...) {
    ErrorCode errorcode = loadData(data);
}

如果以上内容无关紧要,那么您可能想看看expected<T, E>. 它代表任一

  • type 的值T,期望值类型;或者
  • type 的值,E当发生意外结果时使用的错误类型。

使用expectedloadData()签名可能如下所示:

expected<Data, ErrorCode> loadData();

C++11 实现可用:https ://github.com/TartanLlama/expected

于 2019-11-19T13:41:29.713 回答
1

错误处理有多种竞争策略。我不会深入讨论,因为它超出了问题的范围,但是通过返回错误代码进行错误处理只是一种选择。考虑类似std::optional或异常的替代方案,它们在 C++ 中都很常见,但在 Go 中不常见。

如果您有一个旨在返回 Go 风格的错误代码加值的函数,那么您的std::tie解决方案在 C++11 或 C+14 中非常好,尽管在 C++17 中,您更喜欢结构化绑定。

于 2019-11-19T13:13:57.847 回答
0

这样做有什么缺点(性能或其他)?

是的。使用tie,需要复制或移动返回值,如果您避免 ,则不需要tie

auto result = loadData();
if (std::get<0>(result))
    ...//error handling

当然,如果您以后无论如何都要将数据复制或移动到其他地方,例如

data = std::move(std::get<1>(result));

然后使用tie,因为它更短。

于 2019-11-19T13:36:24.613 回答