C++ 中的链可选

Wil*_*nan 7 c++ optional c++17

如何避免在 C++ 中使用链式选项嵌套 if 语句?

例如,如果类型 A 包含 anstd::optional<B> b和类型 B an std::optional<C> c,我希望能够编写如下内容:

const auto v = if_exists(if_exists(a->b)->c);
Run Code Online (Sandbox Code Playgroud)

如果 b 或 c 是空可选项,则 v 将从 c 或空可选项中获取值。

我认为这样嵌套 ifs 会更好:

if (a->b) {
 const auto b = *(a->b);
 if (b->c) {
  const auto c = *(b->c);
 }
}
Run Code Online (Sandbox Code Playgroud)

以下问题似乎朝这个方向发展,但我不确定如何将其调整到我的用例中:Haskell style "Maybe" type & *chaining* in C++11

n. *_* m. 4

您可以执行类似的操作(伪代码;下面提供了可构建代码的链接):

// wrap std::optional for chaining
template <class T> class Maybe {
  std::optional<T> t;

  // ... constructors etc

  // Maybe chaining 
  // If A has a member named m of type M, 
  // then Maybe<A>.fetch(&A::m) returns a Maybe<M>

  template <class M>
  Maybe<M> fetch(M T::*mem_ptr) {
     return (bool(t)) ? Maybe<M>((*t).*mem_ptr) : Maybe<M>() ;
  }

  // Maybe chaining special case 
  // If A has a member named m, which is itself a Maybe<M>,
  // then return it without wrapping it in an additional Maybe

  template <class M>
  Maybe<M> fetch(Maybe<M> T::*mem_ptr) {
     return (bool(t)) ? ((*t).*mem_ptr) : Maybe<M>() ;
  }

};
Run Code Online (Sandbox Code Playgroud)

现在如果你有这个:

 struct C { int d ; }
 struct B { C c; }
 struct A { B b; }
 A a;
 Maybe<A> ma;
Run Code Online (Sandbox Code Playgroud)

你可以这样做

 int d = a.b.c.d;
Run Code Online (Sandbox Code Playgroud)

您不能对 执行相同的操作ma,但您可以使用下一个最好的方法,即:

 Maybe<int> md = ma.fetch(&A::b).fetch(&B::c).fetch(&C::d);
Run Code Online (Sandbox Code Playgroud)

Maybe如果您-ifystruct上面的任何或所有成员,您仍然可以使用它:

 struct C { Maybe<int> d ; }
 struct B { Maybe<C> c; }
 struct A { Maybe<B> b; }
Run Code Online (Sandbox Code Playgroud)

实例(不是生产质量,而是构建)