title: Modern C++ approach for providing optional arguments
body: <p>Let's take the following function declaration:</p>
  <pre><code>void print(SomeType const* i);
  </code></pre>
  <p>Here, the <code>const*</code> nature of the argument <code>i</code> suggest the intent, that the parameter is <em>optional</em>, since it may be <code>nullptr</code>. If this was not intended, the argument would instead just be a <code>const&amp;</code>. Communicating <em>optional</em>-semantics were certainly not the original intent for designing pointers, but using them to do so happens to work just fine for a long time.</p>
  <p>Now, since using raw pointers is generally discouraged in modern C++ (and should be avoided in favor of <code>std::unique_ptr</code> and <code>std::shared_ptr</code> to precisely indicate particular <em>ownership</em>-semantics), I wonder how to properly indicate function parameters' <em>optional</em>-semantics <strong>without passing by value</strong>, i. e. <strong>copying</strong>, as</p>
  <pre><code>void print(std::optional&lt;SomeType&gt; i);
  </code></pre>
  <p>would do.</p>
  <p>After thinking about it for a while I came up with the idea of using:</p>
  <pre><code>void print(std::optional&lt;SomeType const&amp;&gt; i);
  </code></pre>
  <p>This would in fact be most precise. But it turns out that <code>std::optional</code> <a href="https://www.fluentcpp.com/2018/10/05/pros-cons-optional-references/" rel="noreferrer">cannot have reference types</a>.¹</p>
  <p>Also, using</p>
  <pre><code>void print(std::optional&lt;SomeType&gt; const&amp; i);
  </code></pre>
  <p>would in no way be optimal, since then we would <em>require</em> our <code>SomeType</code> to exists in an <code>std::optional</code> on the <em>caller</em>-side, again possibly (or rather <em>likely</em>) requiring a copy <em>there</em>.</p>
  <p><strong>Question:</strong> So what would be a nice modern approach for allowing optional arguments without copying? Is using a raw pointer here still a reasonable approach in modern C++?</p>
  <hr />
  <p>¹: Ironically the depicted reason for why <code>std::optional</code> cannot have reference types (controversy about rebinding or forwarding on assignment) does not apply in the case of <code>std::optional</code>s of <em>const</em> references, since they cannot be assigned to.</p>