你将如何使用Alexandrescu的预期< T>与void函数? [英] How would you use Alexandrescu's Expected<T> with void functions?

查看:152
本文介绍了你将如何使用Alexandrescu的预期< T>与void函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我遇到了这个(IMHO)很好的想法使用一个返回值和一个异常的复合结构 - 期望< T> 。它克服了传统的错误处理方法(例外,错误代码)的许多缺点。

So I ran across this (IMHO) very nice idea of using a composite structure of a return value and an exception - Expected<T>. It overcomes many shortcomings of the traditional methods of error handling (exceptions, error codes).

请参阅 Andrei Alexandrescu的演讲(C ++中的系统错误处理)其幻灯片

异常和错误代码基本上相同的使用场景与功能返回的东西和那些不。 另一方面,预期的< T> 似乎只针对返回值的函数。

The exceptions and error codes have basically the same usage scenarios with functions that return something and the ones that don't. Expected<T>, on the other hand, seems to be targeted only at functions that return values.

,我的问题是:


  • 有任何人尝试过预期< T>

  • Have any of you tried Expected<T> in practice?
  • How would you apply this idiom to functions returning nothing (that is, void functions)?

更新:

我想我应该澄清我的问题。 预期< void> 专业化是有意义的,但我更感兴趣的是如何使用 - 一致的使用习惯。

I guess I should clarify my question. The Expected<void> specialization makes sense, but I'm more interested in how it would be used - the consistent usage idiom. The implementation itself is secondary (and easy).

例如,Alexandrescu给出了这个例子(有点编辑过):

For example, Alexandrescu gives this example (a bit edited):

string s = readline();
auto x = parseInt(s).get(); // throw on error
auto y = parseInt(s); // won’t throw
if (!y.valid()) {
    // ...
}

这个代码是干净的,它只是自然流动。我们需要的价值 - 我们得到它。然而,对于 expected< void> ,必须捕获返回的变量并对它执行一些操作(如 .throwIfError()或某事),这不是那么优雅。显然, .get()对void没有意义。

This code is "clean" in a way that it just flows naturally. We need the value - we get it. However, with expected<void> one would have to capture the returned variable and perform some operation on it (like .throwIfError() or something), which is not as elegant. And obviously, .get() doesn't make sense with void.

如果你有另一个函数,说 toUpper(s),它修改字符串就地,没有返回值?

So, what would your code look like if you had another function, say toUpper(s), which modifies the string in-place and has no return value?

推荐答案


有任何人尝试过Expected;在实践中?

Have any of you tried Expected; in practice?

这是很自然的,我甚至在我看到这个演讲之前使用。

It's quite natural, I used it even before I saw this talk.


如何将这个习语应用于不返回任何东西的函数(即void函数)?

How would you apply this idiom to functions returning nothing (that is, void functions)?

幻灯片中提供的表单有一些细微的含义:

The form presented in the slides has some subtle implications:


  • 例外与值绑定。

  • 可以根据需要处理异常。

  • 如果由于某些原因忽略该值,则异常被抑制。

如果你有 expected< void> ,因为没有人对 void value总是忽略异常。我会强制这是因为我会强制读取从预期< T> 在Alexandrescus类,断言和显式 suppress 成员函数。

This does not hold if you have expected<void>, because since nobody is interested in the void value the exception is always ignored. I would force this as I would force reading from expected<T> in Alexandrescus class, with assertions and an explicit suppress member function. Rethrowing the exception from the destructor is not allowed for good reasons, so it has to be done with assertions.

template <typename T> struct expected;

#ifdef NDEBUG // no asserts
template <> class expected<void> {
  std::exception_ptr spam;
public:
  template <typename E>
  expected(E const& e) : spam(std::make_exception_ptr(e)) {}
  expected(expected&& o) : spam(std::move(o.spam)) {}
  expected() : spam() {}

  bool valid() const { return !spam; }
  void get() const { if (!valid()) std::rethrow_exception(spam); }
  void suppress() {}
};
#else // with asserts, check if return value is checked
      // if all assertions do succeed, the other code is also correct
      // note: do NOT write "assert(expected.valid());"
template <> class expected<void> {
  std::exception_ptr spam;
  mutable std::atomic_bool read; // threadsafe
public:
  template <typename E>
  expected(E const& e) : spam(std::make_exception_ptr(e)), read(false) {}
  expected(expected&& o) : spam(std::move(o.spam)), read(o.read.load()) {}
  expected() : spam(), read(false) {}

  bool valid() const { read=true; return !spam; }
  void get() const { if (!valid()) std::rethrow_exception(spam); }
  void suppress() { read=true; }

  ~expected() { assert(read); }
};
#endif

expected<void> calculate(int i)
{
  if (!i) return std::invalid_argument("i must be non-null");
  return {};
}

int main()
{
  calculate(0).suppress(); // suppressing must be explicit
  if (!calculate(1).valid())
    return 1;
  calculate(5); // assert fails
}

这篇关于你将如何使用Alexandrescu的预期&lt; T&gt;与void函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆