<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<!-- 2019-01-21 Mon 08:44 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>A view of 0 or 1 elements: <code>view::maybe</code></title>
<meta name="generator" content="Org mode" />
<style type="text/css">
 <!--/*--><![CDATA[/*><!--*/
  .title  { text-align: center;
             margin-bottom: .2em; }
  .subtitle { text-align: center;
              font-size: medium;
              font-weight: bold;
              margin-top:0; }
  .todo   { font-family: monospace; color: red; }
  .done   { font-family: monospace; color: green; }
  .priority { font-family: monospace; color: orange; }
  .tag    { background-color: #eee; font-family: monospace;
            padding: 2px; font-size: 80%; font-weight: normal; }
  .timestamp { color: #bebebe; }
  .timestamp-kwd { color: #5f9ea0; }
  .org-right  { margin-left: auto; margin-right: 0px;  text-align: right; }
  .org-left   { margin-left: 0px;  margin-right: auto; text-align: left; }
  .org-center { margin-left: auto; margin-right: auto; text-align: center; }
  .underline { text-decoration: underline; }
  #postamble p, #preamble p { font-size: 90%; margin: .2em; }
  p.verse { margin-left: 3%; }
  pre {
    border: 1px solid #ccc;
    box-shadow: 3px 3px 3px #eee;
    padding: 8pt;
    font-family: monospace;
    overflow: auto;
    margin: 1.2em;
  }
  pre.src {
    position: relative;
    overflow: visible;
    padding-top: 1.2em;
  }
  pre.src:before {
    display: none;
    position: absolute;
    background-color: white;
    top: -10px;
    right: 10px;
    padding: 3px;
    border: 1px solid black;
  }
  pre.src:hover:before { display: inline;}
  /* Languages per Org manual */
  pre.src-asymptote:before { content: 'Asymptote'; }
  pre.src-awk:before { content: 'Awk'; }
  pre.src-C:before { content: 'C'; }
  /* pre.src-C++ doesn't work in CSS */
  pre.src-clojure:before { content: 'Clojure'; }
  pre.src-css:before { content: 'CSS'; }
  pre.src-D:before { content: 'D'; }
  pre.src-ditaa:before { content: 'ditaa'; }
  pre.src-dot:before { content: 'Graphviz'; }
  pre.src-calc:before { content: 'Emacs Calc'; }
  pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
  pre.src-fortran:before { content: 'Fortran'; }
  pre.src-gnuplot:before { content: 'gnuplot'; }
  pre.src-haskell:before { content: 'Haskell'; }
  pre.src-hledger:before { content: 'hledger'; }
  pre.src-java:before { content: 'Java'; }
  pre.src-js:before { content: 'Javascript'; }
  pre.src-latex:before { content: 'LaTeX'; }
  pre.src-ledger:before { content: 'Ledger'; }
  pre.src-lisp:before { content: 'Lisp'; }
  pre.src-lilypond:before { content: 'Lilypond'; }
  pre.src-lua:before { content: 'Lua'; }
  pre.src-matlab:before { content: 'MATLAB'; }
  pre.src-mscgen:before { content: 'Mscgen'; }
  pre.src-ocaml:before { content: 'Objective Caml'; }
  pre.src-octave:before { content: 'Octave'; }
  pre.src-org:before { content: 'Org mode'; }
  pre.src-oz:before { content: 'OZ'; }
  pre.src-plantuml:before { content: 'Plantuml'; }
  pre.src-processing:before { content: 'Processing.js'; }
  pre.src-python:before { content: 'Python'; }
  pre.src-R:before { content: 'R'; }
  pre.src-ruby:before { content: 'Ruby'; }
  pre.src-sass:before { content: 'Sass'; }
  pre.src-scheme:before { content: 'Scheme'; }
  pre.src-screen:before { content: 'Gnu Screen'; }
  pre.src-sed:before { content: 'Sed'; }
  pre.src-sh:before { content: 'shell'; }
  pre.src-sql:before { content: 'SQL'; }
  pre.src-sqlite:before { content: 'SQLite'; }
  /* additional languages in org.el's org-babel-load-languages alist */
  pre.src-forth:before { content: 'Forth'; }
  pre.src-io:before { content: 'IO'; }
  pre.src-J:before { content: 'J'; }
  pre.src-makefile:before { content: 'Makefile'; }
  pre.src-maxima:before { content: 'Maxima'; }
  pre.src-perl:before { content: 'Perl'; }
  pre.src-picolisp:before { content: 'Pico Lisp'; }
  pre.src-scala:before { content: 'Scala'; }
  pre.src-shell:before { content: 'Shell Script'; }
  pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
  /* additional language identifiers per "defun org-babel-execute"
       in ob-*.el */
  pre.src-cpp:before  { content: 'C++'; }
  pre.src-abc:before  { content: 'ABC'; }
  pre.src-coq:before  { content: 'Coq'; }
  pre.src-groovy:before  { content: 'Groovy'; }
  /* additional language identifiers from org-babel-shell-names in
     ob-shell.el: ob-shell is the only babel language using a lambda to put
     the execution function name together. */
  pre.src-bash:before  { content: 'bash'; }
  pre.src-csh:before  { content: 'csh'; }
  pre.src-ash:before  { content: 'ash'; }
  pre.src-dash:before  { content: 'dash'; }
  pre.src-ksh:before  { content: 'ksh'; }
  pre.src-mksh:before  { content: 'mksh'; }
  pre.src-posh:before  { content: 'posh'; }
  /* Additional Emacs modes also supported by the LaTeX listings package */
  pre.src-ada:before { content: 'Ada'; }
  pre.src-asm:before { content: 'Assembler'; }
  pre.src-caml:before { content: 'Caml'; }
  pre.src-delphi:before { content: 'Delphi'; }
  pre.src-html:before { content: 'HTML'; }
  pre.src-idl:before { content: 'IDL'; }
  pre.src-mercury:before { content: 'Mercury'; }
  pre.src-metapost:before { content: 'MetaPost'; }
  pre.src-modula-2:before { content: 'Modula-2'; }
  pre.src-pascal:before { content: 'Pascal'; }
  pre.src-ps:before { content: 'PostScript'; }
  pre.src-prolog:before { content: 'Prolog'; }
  pre.src-simula:before { content: 'Simula'; }
  pre.src-tcl:before { content: 'tcl'; }
  pre.src-tex:before { content: 'TeX'; }
  pre.src-plain-tex:before { content: 'Plain TeX'; }
  pre.src-verilog:before { content: 'Verilog'; }
  pre.src-vhdl:before { content: 'VHDL'; }
  pre.src-xml:before { content: 'XML'; }
  pre.src-nxml:before { content: 'XML'; }
  /* add a generic configuration mode; LaTeX export needs an additional
     (add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
  pre.src-conf:before { content: 'Configuration File'; }

  table { border-collapse:collapse; }
  caption.t-above { caption-side: top; }
  caption.t-bottom { caption-side: bottom; }
  td, th { vertical-align:top;  }
  th.org-right  { text-align: center;  }
  th.org-left   { text-align: center;   }
  th.org-center { text-align: center; }
  td.org-right  { text-align: right;  }
  td.org-left   { text-align: left;   }
  td.org-center { text-align: center; }
  dt { font-weight: bold; }
  .footpara { display: inline; }
  .footdef  { margin-bottom: 1em; }
  .figure { padding: 1em; }
  .figure p { text-align: center; }
  .equation-container {
    display: table;
    text-align: center;
    width: 100%;
  }
  .equation {
    vertical-align: middle;
  }
  .equation-label {
    display: table-cell;
    text-align: right;
    vertical-align: middle;
  }
  .inlinetask {
    padding: 10px;
    border: 2px solid gray;
    margin: 10px;
    background: #ffffcc;
  }
  #org-div-home-and-up
   { text-align: right; font-size: 70%; white-space: nowrap; }
  textarea { overflow-x: auto; }
  .linenr { font-size: smaller }
  .code-highlighted { background-color: #ffff00; }
  .org-info-js_info-navigation { border-style: none; }
  #org-info-js_console-label
    { font-size: 10px; font-weight: bold; white-space: nowrap; }
  .org-info-js_search-highlight
    { background-color: #ffff00; color: #000000; font-weight: bold; }
  .org-svg { width: 90%; }
  /*]]>*/-->
</style>
<link rel="stylesheet" type="text/css" href="https://raw.githubusercontent.com/steve-downey/css/master/smd-zenburn.css" />
<script type="text/javascript">
/*
@licstart  The following is the entire license notice for the
JavaScript code in this tag.

Copyright (C) 2012-2018 Free Software Foundation, Inc.

The JavaScript code in this tag is free software: you can
redistribute it and/or modify it under the terms of the GNU
General Public License (GNU GPL) as published by the Free Software
Foundation, either version 3 of the License, or (at your option)
any later version.  The code is distributed WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.

As additional permission under GNU GPL version 3 section 7, you
may distribute non-source (e.g., minimized or compacted) forms of
that code without the copy of the GNU GPL normally required by
section 4, provided you include this license notice and a URL
through which recipients can access the Corresponding Source.


@licend  The above is the entire license notice
for the JavaScript code in this tag.
*/
<!--/*--><![CDATA[/*><!--*/
 function CodeHighlightOn(elem, id)
 {
   var target = document.getElementById(id);
   if(null != target) {
     elem.cacheClassElem = elem.className;
     elem.cacheClassTarget = target.className;
     target.className = "code-highlighted";
     elem.className   = "code-highlighted";
   }
 }
 function CodeHighlightOff(elem, id)
 {
   var target = document.getElementById(id);
   if(elem.cacheClassElem)
     elem.className = elem.cacheClassElem;
   if(elem.cacheClassTarget)
     target.className = elem.cacheClassTarget;
 }
/*]]>*///-->
</script>
</head>
<body>
<div id="content">
<h1 class="title">A view of 0 or 1 elements: <code>view::maybe</code></h1>
<ul class="org-ul">
<li>Document number: P1255R2</li>
<li>Date:  2018-11-26</li>
<li>Author: Steve Downey &lt;sdowney2@bloomberg.net&gt;, &lt;sdowney@gmail.com&gt;</li>
<li>Audience: LEWG</li>
</ul>

<div class="ABSTRACT">
<p>
Abstract: This paper proposes <code>view::maybe</code> a range adaptor that produces a view with cardinality 0 or 1 which adapts nullable types such as <code>std::optional</code> and pointer types.
</p>

</div>

<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#org713b8b7">1. Changes since R1</a></li>
<li><a href="#org8ec445f">2. Changes since R0</a></li>
<li><a href="#org9928729">3. Motivation</a></li>
<li><a href="#org4bb0491">4. Proposal</a></li>
<li><a href="#orgfa4dba1">5. Design</a></li>
<li><a href="#org1709e52">6. Synopsis</a></li>
<li><a href="#org6af36fe">7. Impact on the standard</a></li>
<li><a href="#orgea25eca">8. References</a></li>
</ul>
</div>
</div>

<div id="outline-container-org713b8b7" class="outline-2">
<h2 id="org713b8b7"><span class="section-number-2">1</span> Changes since R1</h2>
<div class="outline-text-2" id="text-1">
</div>
<div id="outline-container-orga55a526" class="outline-3">
<h3 id="orga55a526"><span class="section-number-3">1.1</span> Refer to view::all</h3>
<div class="outline-text-3" id="text-1-1">
<p>
Behavior of capture vs refer is similar to how view::all works over the expression it is given
</p>
</div>
</div>
<div id="outline-container-org42160d4" class="outline-3">
<h3 id="org42160d4"><span class="section-number-3">1.2</span> Use wording 'range adaptor object'</h3>
<div class="outline-text-3" id="text-1-2">
<p>
Match current working paper language
</p>
</div>
</div>
</div>
<div id="outline-container-org8ec445f" class="outline-2">
<h2 id="org8ec445f"><span class="section-number-2">2</span> Changes since R0</h2>
<div class="outline-text-2" id="text-2">
</div>
<div id="outline-container-org6aaae52" class="outline-3">
<h3 id="org6aaae52"><span class="section-number-3">2.1</span> Remove customization point objects</h3>
<div class="outline-text-3" id="text-2-1">
<p>
Removed view::maybe_has_value and view::maybe_value, instead requiring that the nullable type be dereferenceable and contextually convertable to bool.
</p>
</div>
</div>
<div id="outline-container-orge2bd047" class="outline-3">
<h3 id="orge2bd047"><span class="section-number-3">2.2</span> Concept <code>Nullable</code>, for exposition</h3>
<div class="outline-text-3" id="text-2-2">
<p>
Concept Nullable, which is Readable and contextually convertable to bool
</p>
</div>
</div>
<div id="outline-container-orgde1cb78" class="outline-3">
<h3 id="orgde1cb78"><span class="section-number-3">2.3</span> Capture rvalues by decay copy</h3>
<div class="outline-text-3" id="text-2-3">
<p>
Hold a copy when constructing a view over a nullable rvalue.
</p>
</div>
</div>
<div id="outline-container-orgdc714a2" class="outline-3">
<h3 id="orgdc714a2"><span class="section-number-3">2.4</span> Remove maybe_view as a specified type</h3>
<div class="outline-text-3" id="text-2-4">
<p>
Introduced two exposition types, one safely holding a copy, the other referring to the nullable
</p>
</div>
</div>
</div>

<div id="outline-container-org9928729" class="outline-2">
<h2 id="org9928729"><span class="section-number-2">3</span> Motivation</h2>
<div class="outline-text-2" id="text-3">
<p>
In writing range transformation pipelines it is useful to be able to lift a nullable value into a view that is either empty or contains the value held by the nullable. The adapter <code>view::single</code> fills a similar purpose for non-nullable values, lifting a single value into a view, and <code>view::empty</code> provides a range of no values of a given type. A <code>view::maybe</code> adaptor also allows nullable values to be treated as ranges when it is otherwise undesirable to make them containers, for example <code>std::optional</code>.
</p>

<div class="org-src-container">
<pre class="src src-C++"><span style="color: #005cc5;">std</span>::<span style="color: #005cc5;">vector</span>&lt;<span style="color: #005cc5;">std</span>::<span style="color: #005cc5;">optional</span>&lt;<span style="color: #005cc5;">int</span>&gt;&gt; <span style="color: #24292e;">v</span>{
  <span style="color: #005cc5;">std</span>::<span style="color: #005cc5;">optional</span>&lt;<span style="color: #005cc5;">int</span>&gt;{42},
  <span style="color: #005cc5;">std</span>::<span style="color: #005cc5;">optional</span>&lt;<span style="color: #005cc5;">int</span>&gt;{},
  <span style="color: #005cc5;">std</span>::<span style="color: #005cc5;">optional</span>&lt;<span style="color: #005cc5;">int</span>&gt;{6 * 9}};

<span style="color: #d73a49; font-weight: bold;">auto</span> <span style="color: #24292e;">r</span> = <span style="color: #005cc5;">view</span>::join(<span style="color: #005cc5;">view</span>::transform(v, <span style="color: #005cc5;">view</span>::maybe));

<span style="color: #d73a49; font-weight: bold;">for</span> (<span style="color: #d73a49; font-weight: bold;">auto</span> <span style="color: #24292e;">i</span> : r) {
    <span style="color: #005cc5;">std</span>::cout &lt;&lt; i; <span style="color: #6a737d; font-style: italic;">// </span><span style="color: #6a737d; font-style: italic;">prints 42 and 42</span>
}
</pre>
</div>

<p>
In addition to range transformation pipelines, <code>view::maybe</code> can be used in range based for loops, allowing the nullable value to not be dereferenced within the body. This is of small value in small examples in contrast to testing the nullable in an if statement, but with longer bodies the dereference is often far away from the test. Often the first line in the body of the <code>if</code> is naming the dereferenced nullable, and lifting the dereference into the for loop eliminates some boilerplate code, the same way that range based for loops do.
</p>

<div class="org-src-container">
<pre class="src src-C++">{
    <span style="color: #d73a49; font-weight: bold;">auto</span>&amp;&amp; <span style="color: #24292e;">opt</span> = possible_value();
    <span style="color: #d73a49; font-weight: bold;">if</span> (*opt) {
        <span style="color: #6a737d; font-style: italic;">// </span><span style="color: #6a737d; font-style: italic;">a few dozen lines ...</span>
        use(*opt); <span style="color: #6a737d; font-style: italic;">// </span><span style="color: #6a737d; font-style: italic;">is *opt OK ?</span>
    }
}

<span style="color: #d73a49; font-weight: bold;">for</span> (<span style="color: #d73a49; font-weight: bold;">auto</span>&amp;&amp; <span style="color: #24292e;">opt</span> : <span style="color: #005cc5;">view</span>::maybe(possible_value())) {
    <span style="color: #6a737d; font-style: italic;">// </span><span style="color: #6a737d; font-style: italic;">a few dozen lines ...</span>
    use(opt); <span style="color: #6a737d; font-style: italic;">// </span><span style="color: #6a737d; font-style: italic;">opt is OK</span>
}
</pre>
</div>
</div>
</div>


<div id="outline-container-org4bb0491" class="outline-2">
<h2 id="org4bb0491"><span class="section-number-2">4</span> Proposal</h2>
<div class="outline-text-2" id="text-4">
<p>
Add a range adaptor object <code>view::maybe</code>, returning a view over a nullable object, capturing by value temporary nullables. A <code>Nullable</code> object is one that is both contextually convertable to bool and which models the <code>Readable</code> concept. Non void pointers, <code>std::optional</code>, and the proposed <code>outcome</code> and <code>expected</code> types all model Nullable.
</p>
</div>
</div>

<div id="outline-container-orgfa4dba1" class="outline-2">
<h2 id="orgfa4dba1"><span class="section-number-2">5</span> Design</h2>
<div class="outline-text-2" id="text-5">
<p>
The basis of the design is to hybridize <code>view::single</code> and <code>view::empty</code>. If the underlying object claims to hold a value, as determined by checking if the object when converted to bool is true, <code>begin</code> and <code>end</code> of the view are equivalent to the address of the held value within the underlying object and one past the underlying object.  If the underlying object does not have a value, <code>begin</code> and <code>end</code> return <code>nullptr</code>.
</p>

<p>
The <code>view::maybe</code> range adapter object will create either a safe view, containing a move initialized decay_copy of the nullable, or a reference view, referring to the nullable value, depending on the deduced referenceness of the template parameter. This is similar to <code>view::all</code>, without attempting to handle its third case defaulting to using <code>subrange</code>, as there seems to be no good model of an expression that falls into that third category.
</p>
</div>
</div>

<div id="outline-container-org1709e52" class="outline-2">
<h2 id="org1709e52"><span class="section-number-2">6</span> Synopsis</h2>
<div class="outline-text-2" id="text-6">
<div class="org-src-container">
<pre class="src src-C++"><span style="color: #d73a49; font-weight: bold;">namespace</span> <span style="color: #005cc5;">std</span>::<span style="color: #005cc5;">ranges</span> {

<span style="color: #6a737d; font-style: italic;">// </span><span style="color: #6a737d; font-style: italic;">For Exposition</span>
<span style="color: #d73a49; font-weight: bold;">template</span>&lt;<span style="color: #d73a49; font-weight: bold;">class</span>&gt; <span style="color: #d73a49; font-weight: bold;">struct</span> <span style="color: #005cc5;">dereference_type</span> {};

<span style="color: #d73a49; font-weight: bold;">template</span>&lt;<span style="color: #d73a49; font-weight: bold;">class</span> <span style="color: #005cc5;">D</span>&gt;
<span style="color: #005cc5;">requires</span>
<span style="color: #d73a49; font-weight: bold;">requires</span>(<span style="color: #d73a49; font-weight: bold;">const</span> <span style="color: #005cc5;">D</span>&amp; <span style="color: #24292e;">d</span>) {{ *d } -&gt; <span style="color: #d73a49; font-weight: bold;">auto</span>&amp;&amp;; }
<span style="color: #d73a49; font-weight: bold;">struct</span> <span style="color: #005cc5;">dereference_type</span>&lt;<span style="color: #005cc5;">D</span>&gt; {
    <span style="color: #d73a49; font-weight: bold;">using</span> <span style="color: #005cc5;">type</span> = <span style="color: #d73a49; font-weight: bold;">decltype</span>(*declval&lt;<span style="color: #d73a49; font-weight: bold;">const</span> <span style="color: #005cc5;">D</span>&amp;&gt;());
};

<span style="color: #d73a49; font-weight: bold;">template</span>&lt;<span style="color: #d73a49; font-weight: bold;">class</span> <span style="color: #005cc5;">D</span>&gt;
<span style="color: #d73a49; font-weight: bold;">using</span> <span style="color: #005cc5;">dereference_t</span> = <span style="color: #d73a49; font-weight: bold;">typename</span> <span style="color: #005cc5;">dereference_type</span>&lt;<span style="color: #005cc5;">D</span>&gt;::type;


<span style="color: #d73a49; font-weight: bold;">template</span>&lt;<span style="color: #d73a49; font-weight: bold;">class</span> <span style="color: #005cc5;">T</span>&gt;
<span style="color: #d73a49; font-weight: bold;">concept</span> <span style="color: #005cc5;">bool</span> <span style="color: #24292e;">ContextualBool</span> =
    <span style="color: #d73a49; font-weight: bold;">requires</span>(<span style="color: #d73a49; font-weight: bold;">const</span> <span style="color: #005cc5;">T</span>&amp; <span style="color: #24292e;">t</span>) {
    {<span style="color: #005cc5;">bool</span>(t)} -&gt; <span style="color: #005cc5;">bool</span>;
};

<span style="color: #d73a49; font-weight: bold;">template</span> &lt;<span style="color: #d73a49; font-weight: bold;">class</span> <span style="color: #005cc5;">T</span>&gt;
<span style="color: #d73a49; font-weight: bold;">concept</span> <span style="color: #005cc5;">bool</span> <span style="color: #24292e;">Nullable</span> =
    <span style="color: #005cc5;">Readable</span>&lt;<span style="color: #005cc5;">remove_reference_t</span>&lt;<span style="color: #005cc5;">T</span>&gt;&gt; &amp;&amp;
    <span style="color: #005cc5;">ContextualBool</span>&lt;<span style="color: #005cc5;">T</span>&gt; &amp;&amp;
    <span style="color: #d73a49; font-weight: bold;">requires</span> (<span style="color: #d73a49; font-weight: bold;">const</span> <span style="color: #005cc5;">T</span>&amp; <span style="color: #24292e;">t</span>) {
    <span style="color: #d73a49; font-weight: bold;">typename</span> <span style="color: #005cc5;">dereference_t</span>&lt;<span style="color: #005cc5;">T</span>&gt;;
    <span style="color: #005cc5;">is_object_v</span>&lt;<span style="color: #005cc5;">dereference_t</span>&lt;<span style="color: #005cc5;">T</span>&gt;&gt;;
};


<span style="color: #d73a49; font-weight: bold;">template</span> &lt;<span style="color: #005cc5;">Nullable</span> <span style="color: #24292e;">Maybe</span>&gt;
<span style="color: #005cc5;">requires</span> <span style="color: #005cc5;">is_object_v</span>&lt;R&gt;
<span style="color: #d73a49; font-weight: bold;">class</span> safe_maybe_view
    : <span style="color: #d73a49; font-weight: bold;">public</span> <span style="color: #005cc5;">view_interface</span>&lt;<span style="color: #005cc5;">safe_maybe_view</span>&lt;Maybe&gt;&gt; {
  <span style="color: #d73a49; font-weight: bold;">private</span>:
    <span style="color: #d73a49; font-weight: bold;">using</span> <span style="color: #005cc5;">T</span> = <span style="color: #005cc5;">decay_t</span>&lt;<span style="color: #005cc5;">remove_reference_t</span>&lt;<span style="color: #005cc5;">dereference_t</span>&lt;Maybe&gt;&gt;&gt;;
    <span style="color: #d73a49; font-weight: bold;">using</span> <span style="color: #005cc5;">M</span> = <span style="color: #005cc5;">remove_cv_t</span>&lt;<span style="color: #005cc5;">remove_reference_t</span>&lt;Maybe&gt;&gt;;

    <span style="color: #005cc5;">semiregular</span>&lt;<span style="color: #005cc5;">M</span>&gt; <span style="color: #24292e;">value_</span>;

  <span style="color: #d73a49; font-weight: bold;">public</span>:
    safe_maybe_view() = <span style="color: #d73a49; font-weight: bold;">default</span>;

    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #d73a49; font-weight: bold;">explicit</span> <span style="color: #6f42c1;">safe_maybe_view</span>(<span style="color: #005cc5;">Maybe</span> <span style="color: #d73a49; font-weight: bold;">const</span>&amp; <span style="color: #24292e;">maybe</span>);
    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #d73a49; font-weight: bold;">explicit</span> <span style="color: #6f42c1;">safe_maybe_view</span>(<span style="color: #005cc5;">Maybe</span>&amp;&amp; <span style="color: #24292e;">maybe</span>);
    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #005cc5;">T</span>*       <span style="color: #6f42c1;">begin</span>() <span style="color: #d73a49; font-weight: bold;">noexcept</span>;
    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #d73a49; font-weight: bold;">const</span> <span style="color: #005cc5;">T</span>* <span style="color: #6f42c1;">begin</span>() <span style="color: #d73a49; font-weight: bold;">const</span> <span style="color: #d73a49; font-weight: bold;">noexcept</span>;
    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #005cc5;">T</span>*       <span style="color: #6f42c1;">end</span>() <span style="color: #d73a49; font-weight: bold;">noexcept</span> ;

    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #d73a49; font-weight: bold;">const</span> <span style="color: #005cc5;">T</span>* <span style="color: #6f42c1;">end</span>() <span style="color: #d73a49; font-weight: bold;">const</span> <span style="color: #d73a49; font-weight: bold;">noexcept</span> ;

    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #005cc5;">ptrdiff_t</span> <span style="color: #6f42c1;">size</span>() <span style="color: #d73a49; font-weight: bold;">noexcept</span> ;

    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #005cc5;">T</span>* <span style="color: #6f42c1;">data</span>() <span style="color: #d73a49; font-weight: bold;">noexcept</span> ;

    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #d73a49; font-weight: bold;">const</span> <span style="color: #005cc5;">T</span>* <span style="color: #6f42c1;">data</span>() <span style="color: #d73a49; font-weight: bold;">const</span> <span style="color: #d73a49; font-weight: bold;">noexcept</span>;
};

<span style="color: #d73a49; font-weight: bold;">template</span> &lt;<span style="color: #005cc5;">Nullable</span> <span style="color: #24292e;">Maybe</span>&gt;
<span style="color: #005cc5;">requires</span> <span style="color: #005cc5;">is_object_v</span>&lt;R&gt;
<span style="color: #d73a49; font-weight: bold;">class</span> ref_maybe_view
    : <span style="color: #d73a49; font-weight: bold;">public</span> <span style="color: #005cc5;">view_interface</span>&lt;<span style="color: #005cc5;">ref_maybe_view</span>&lt;<span style="color: #005cc5;">Maybe</span>&gt;&gt; {
    <span style="color: #005cc5;">remove_reference_t</span>&lt;<span style="color: #005cc5;">Maybe</span>&gt;* <span style="color: #24292e;">value_</span>;
    <span style="color: #d73a49; font-weight: bold;">using</span> <span style="color: #005cc5;">R</span> = <span style="color: #005cc5;">remove_reference_t</span>&lt;<span style="color: #d73a49; font-weight: bold;">decltype</span>(**value_)&gt;;

  <span style="color: #d73a49; font-weight: bold;">public</span>:
    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #6f42c1;">ref_maybe_view</span>() = <span style="color: #d73a49; font-weight: bold;">default</span>;
    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #6f42c1;">ref_maybe_view</span>(<span style="color: #005cc5;">ref_maybe_view</span> <span style="color: #d73a49; font-weight: bold;">const</span>&amp;) = <span style="color: #d73a49; font-weight: bold;">default</span>;

    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #d73a49; font-weight: bold;">explicit</span> <span style="color: #6f42c1;">ref_maybe_view</span>(<span style="color: #005cc5;">Maybe</span>&amp; <span style="color: #24292e;">maybe</span>);

    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #005cc5;">R</span>*       <span style="color: #6f42c1;">begin</span>() <span style="color: #d73a49; font-weight: bold;">noexcept</span>;
    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #d73a49; font-weight: bold;">const</span> <span style="color: #005cc5;">R</span>* <span style="color: #6f42c1;">begin</span>() <span style="color: #d73a49; font-weight: bold;">const</span> <span style="color: #d73a49; font-weight: bold;">noexcept</span>;
    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #005cc5;">R</span>*       <span style="color: #6f42c1;">end</span>() <span style="color: #d73a49; font-weight: bold;">noexcept</span> ;

    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #d73a49; font-weight: bold;">const</span> <span style="color: #005cc5;">R</span>* <span style="color: #6f42c1;">end</span>() <span style="color: #d73a49; font-weight: bold;">const</span> <span style="color: #d73a49; font-weight: bold;">noexcept</span>;

    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #005cc5;">ptrdiff_t</span> <span style="color: #6f42c1;">size</span>() <span style="color: #d73a49; font-weight: bold;">noexcept</span>;

    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #005cc5;">R</span>* <span style="color: #6f42c1;">data</span>() <span style="color: #d73a49; font-weight: bold;">noexcept</span>;

    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #d73a49; font-weight: bold;">const</span> <span style="color: #005cc5;">R</span>* <span style="color: #6f42c1;">data</span>() <span style="color: #d73a49; font-weight: bold;">const</span> <span style="color: #d73a49; font-weight: bold;">noexcept</span>;
};

<span style="color: #d73a49; font-weight: bold;">namespace</span> <span style="color: #005cc5;">view</span> {
<span style="color: #d73a49; font-weight: bold;">struct</span> <span style="color: #005cc5;">__maybe_fn</span> {
    <span style="color: #d73a49; font-weight: bold;">template</span> &lt;<span style="color: #005cc5;">Nullable</span> <span style="color: #24292e;">T</span>&gt;
    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #d73a49; font-weight: bold;">auto</span> <span style="color: #d73a49; font-weight: bold;">operator</span><span style="color: #6f42c1;">()</span>(<span style="color: #005cc5;">T</span>&amp;&amp; <span style="color: #24292e;">t</span>) <span style="color: #d73a49; font-weight: bold;">const</span>
        <span style="color: #d73a49; font-weight: bold;">noexcept</span>(<span style="color: #d73a49; font-weight: bold;">noexcept</span>(ref_maybe_view{<span style="color: #005cc5;">std</span>::forward&lt;<span style="color: #005cc5;">T</span>&gt;(t)}))
        <span style="color: #005cc5;">requires</span> <span style="color: #005cc5;">std</span>::<span style="color: #005cc5;">is_reference_v</span>&lt;<span style="color: #005cc5;">T</span>&gt; &amp;&amp;
        <span style="color: #d73a49; font-weight: bold;">requires</span> {ref_maybe_view{<span style="color: #005cc5;">std</span>::forward&lt;<span style="color: #005cc5;">T</span>&gt;(t)};}
    {
        <span style="color: #d73a49; font-weight: bold;">return</span> ref_maybe_view{<span style="color: #005cc5;">std</span>::forward&lt;<span style="color: #005cc5;">T</span>&gt;(t)};
    }

    <span style="color: #d73a49; font-weight: bold;">template</span> &lt;<span style="color: #005cc5;">Nullable</span> <span style="color: #24292e;">T</span>&gt;
    <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #d73a49; font-weight: bold;">auto</span> <span style="color: #d73a49; font-weight: bold;">operator</span><span style="color: #6f42c1;">()</span>(<span style="color: #005cc5;">T</span>&amp;&amp; <span style="color: #24292e;">t</span>) <span style="color: #d73a49; font-weight: bold;">const</span>
        <span style="color: #d73a49; font-weight: bold;">noexcept</span>(<span style="color: #d73a49; font-weight: bold;">noexcept</span>(safe_maybe_view{<span style="color: #005cc5;">std</span>::forward&lt;<span style="color: #005cc5;">T</span>&gt;(t)}))
        <span style="color: #d73a49; font-weight: bold;">requires</span> <span style="color: #d73a49; font-weight: bold;">!</span><span style="color: #005cc5;">std</span>::<span style="color: #005cc5;">is_reference_v</span>&lt;<span style="color: #005cc5;">T</span>&gt; &amp;&amp;
        <span style="color: #d73a49; font-weight: bold;">requires</span> {safe_maybe_view{<span style="color: #005cc5;">std</span>::forward&lt;<span style="color: #005cc5;">T</span>&gt;(t)};}
    {
        <span style="color: #d73a49; font-weight: bold;">return</span> safe_maybe_view{<span style="color: #005cc5;">std</span>::forward&lt;<span style="color: #005cc5;">T</span>&gt;(t)};
    }
};

<span style="color: #d73a49; font-weight: bold;">inline</span> <span style="color: #d73a49; font-weight: bold;">constexpr</span> <span style="color: #005cc5;">__maybe_fn</span> <span style="color: #24292e;">maybe</span>{};

} <span style="color: #6a737d; font-style: italic;">// </span><span style="color: #6a737d; font-style: italic;">namespace view</span>
} <span style="color: #6a737d; font-style: italic;">// </span><span style="color: #6a737d; font-style: italic;">namespace std::ranges</span>
</pre>
</div>


<p>
[Example:
</p>
<div class="org-src-container">
<pre class="src src-C++">   <span style="color: #005cc5;">optional</span> <span style="color: #24292e;">o</span>{4};
   <span style="color: #d73a49; font-weight: bold;">for</span> (<span style="color: #005cc5;">int</span> <span style="color: #24292e;">i</span> : <span style="color: #005cc5;">view</span>::maybe(o))
     cout &lt;&lt; i; <span style="color: #6a737d; font-style: italic;">// </span><span style="color: #6a737d; font-style: italic;">prints 4</span>

   <span style="color: #005cc5;">maybe_view</span> <span style="color: #24292e;">e</span>{ };
   <span style="color: #d73a49; font-weight: bold;">for</span> (<span style="color: #005cc5;">int</span> <span style="color: #24292e;">i</span> : <span style="color: #005cc5;">view</span>::maybe(<span style="color: #005cc5;">std</span>::optional{}))
     cout &lt;&lt; i; <span style="color: #6a737d; font-style: italic;">// </span><span style="color: #6a737d; font-style: italic;">does not print</span>

   <span style="color: #005cc5;">int</span>        <span style="color: #24292e;">j</span>  = 8;
   <span style="color: #005cc5;">int</span>*       <span style="color: #24292e;">pj</span> = &amp;j;
   <span style="color: #d73a49; font-weight: bold;">for</span> (<span style="color: #d73a49; font-weight: bold;">auto</span> <span style="color: #24292e;">i</span> : <span style="color: #005cc5;">view</span>::maybe(pj))
     <span style="color: #005cc5;">std</span>::cout &lt;&lt; i; <span style="color: #6a737d; font-style: italic;">// </span><span style="color: #6a737d; font-style: italic;">prints 8</span>
</pre>
</div>

<p>
— end example ]
</p>
</div>

<div id="outline-container-org0047210" class="outline-3">
<h3 id="org0047210"><span class="section-number-3">6.1</span> <code>view::maybe</code></h3>
<div class="outline-text-3" id="text-6-1">
<p>
<code>view::maybe</code> returns a View over a Nullable that is either empty if the nullable is empty, or includes the contents of the nullable obhect.
</p>

<p>
The name view::maybe denotes a range adaptor object ([range.adaptor.object]). For some subexpression E, the expression view::maybe(E) is expression-equivalent to:
</p>

<p>
&#x2013; safe_maybe_view{E}, if the expression is well formed, where E is decay copied into the safe_maybe_view
</p>

<p>
&#x2013; otherwise ref_maybe_view{}, if that expression is well formed, where ref_maybe_view refers to E
</p>

<p>
&#x2013; otherwise view::maybe(E) is ill-formed
</p>

<p>
Note: Whenever view::maybe(E) is a valid expression, it is a prvalue whose type models View. — end note ]
</p>
</div>
</div>
</div>

<div id="outline-container-org6af36fe" class="outline-2">
<h2 id="org6af36fe"><span class="section-number-2">7</span> Impact on the standard</h2>
<div class="outline-text-2" id="text-7">
<p>
A pure library extension, affecting no other parts of the library or language.
</p>
</div>
</div>

<div id="outline-container-orgea25eca" class="outline-2">
<h2 id="orgea25eca"><span class="section-number-2">8</span> References</h2>
<div class="outline-text-2" id="text-8">
<p>
[P0896R3] Eric Niebler, Casey Carter, Christopher Di Bella. The One Ranges Proposal URL: <a href="https://wg21.link/p0896r3">https://wg21.link/p0896r3</a>
</p>

<p>
[P0323R7] Vicente Botet, JF Bastien. std::expected URL: <a href="https://wg21.link/p0323r7">https://wg21.link/p0323r7</a>
</p>
</div>
</div>
</div>
</body>
</html>
