title: How to flatten the nested std::optional?
body: <p><em>note: this question was briefly marked as a duplicate of <a href="https://stackoverflow.com/questions/45149760/is-there-a-safe-navigation-operator-for-c/45155744#45155744">this</a>, but it is not an exact duplicate since I am asking about std::optionals specifically. Still a good question to read if you care about general case.</em></p>
  <p>Assume I have nested optionals, something like this(dumb toy example):</p>
  <pre><code>struct Person{
      const std::string first_name;
      const std::optional&lt;std::string&gt; middle_name;
      const std::string last_name;
  };
  struct Form{
      std::optional&lt;Person&gt; person;
  };
  </code></pre>
  <p>and this spammy function:</p>
  <pre><code>void PrintMiddleName(const std::optional&lt;Form&gt; form){
      if (form.has_value() &amp;&amp; form-&gt;person.has_value() &amp;&amp; form-&gt;person-&gt;middle_name.has_value()) {
          std::cout &lt;&lt; *(*(*form).person).middle_name &lt;&lt; std::endl; 
      } else {
          std::cout &lt;&lt; &quot;&lt;none&gt;&quot;  &lt;&lt; std::endl; 
      }
  }
  </code></pre>
  <p>What would be the best way to flatten this optional check?
  I have made something like this, it is not variadic, but I do not care that much about that(I can add one more level(overload with <code>membr3</code>) if really necessary, and everything beyond that is terrible code anyway).</p>
  <pre><code>template&lt;typename T, typename M&gt;
  auto flatten_opt(const std::optional&lt;T&gt; opt, M membr){
      if (opt.has_value() &amp;&amp; (opt.value().*membr).has_value()){
          return std::optional{*((*opt).*membr)};
      }
      return decltype(std::optional{*((*opt).*membr)}){};
  }
  
  template&lt;typename T, typename M1, typename M2&gt;
  auto ret_val_helper(){
      // better code would use declval here since T might not be 
      // default constructible.
      T t;
      M1 m1;
      M2 m2;
      return ((t.*m1).value().*m2).value();
  }
  
  template&lt;typename T, typename M1, typename M2&gt;
  std::optional&lt;decltype(ret_val_helper&lt;T, M1, M2&gt;())&gt; flatten_opt(const std::optional&lt;T&gt; opt, M1 membr1, M2 membr2){
      if (opt.has_value() &amp;&amp; (opt.value().*membr1).has_value()){
          const auto&amp; deref1 = *((*opt).*membr1);
          if ((deref1.*membr2).has_value()) {
              return std::optional{*(deref1.*membr2)};
          }
      }
      return {};
  }
  
  void PrintMiddleName2(const std::optional&lt;Form&gt; form){
      auto flat  = flatten_opt(form, &amp;Form::person, &amp;Person::middle_name);
      if (flat) {
          std::cout &lt;&lt; *flat;
      }
      else {
          std::cout &lt;&lt; &quot;&lt;none&gt;&quot;  &lt;&lt; std::endl; 
      }
  }
  </code></pre>
  <p><a href="https://godbolt.org/z/Wa11Yx3r5" rel="noreferrer">godbolt</a></p>
  <p>notes:</p>
  <ul>
  <li>I do not want to switch away from <code>std::optional</code> to <a href="https://github.com/TartanLlama/optional" rel="noreferrer">some better optional</a>.</li>
  <li>I do not care that much about perf, unless I return a pointer I must make copy(unless arg is temporary) since <code>std::optional</code> does not support references.</li>
  <li>I do not care about <code>flatten_has_value</code> function(although it is useful), since if there is a way to nicely flatten the nested optionals there is also a way to write that function.</li>
  <li>I know my code <em>looks</em> like it works, but it is quite ugly, so I am wondering if there is a nicer solution.</li>
  </ul>