<html><head><meta charset="UTF-8">
<title>Revisiting in-place tag types for any/optional/variant</title>
  <style type='text/css'>
  body {font-variant-ligatures: none;}
  p {text-align:justify}
  li {text-align:justify}
  blockquote.note, div.note
  {
          background-color:#E0E0E0;
          padding-left: 15px;
          padding-right: 15px;
          padding-top: 1px;
          padding-bottom: 1px;
  }
  p code {color:navy}
  ins p code {color:#00A000}
  p ins code {color:#00A000}
  p del code {color:#A00000}
  ins {color:#00A000}
  del {color:#A00000}
  table#boilerplate { border:0 }
  table#boilerplate td { padding-left: 2em }
  table.bordered, table.bordered th, table.bordered td {
    border: 1px solid;
    text-align: center;
  }
  ins.block {color:#00A000; text-decoration: none}
  del.block {color:#A00000; text-decoration: none}
  </style>
</head><body>
<table id="boilerplate">
<tr><td>Document number</td><td>P0504R0</td></tr>
<tr><td>Date</td><td>2016-11-09</td></tr>
<tr><td>Project</td><td>Programming Language C++, Library Working Group</td></tr>
<tr><td>Reply-to</td><td>Jonathan Wakely &lt;cxx&#x40;kayari.org&gt;</td></tr>
</table><hr>
<h1>Revisiting in-place tag types for any/optional/variant</h1>
<h2>Introduction</h2>

<p><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0032r3.pdf">P0032R3</a> was accepted in Oulu, although the part of the proposal
changing the <code>in_place</code> tag types was controversial and there were two polls
taken, for the complete proposal and only the less controversial part of it. In
the end the complete proposal was accepted, however there are NB ballot
comments pointing out problems with the controversial part. This proposal
undoes that part to address CH 3 (the first) in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0488r0.pdf">P0488R0</a>, and also
resolves GB 46 in the process.</p>

<h2>Rationale</h2>

<p>The new tag types are function references, to one of a set of overloaded
functions and function templates, in order to allow <code>in_place</code> to be an
overloaded name that can be used with no template argument list, or a
template argument list consisting of either a single type argument or a single
non-type argument. This is considered to be too clever and liable to confuse
users. More importantly, they introduce ambiguities and errors for cases
that work fine with traditional structs as tag types.</p>

<p>When attempting to pass the <code>in_place</code> tag (without arguments) as a deduced
argument for a function template the compiler doesn't know that the
non-template function is intended, and so the name is ambiguous. This example
fails to compile, because the second <code>in_place</code> is ambiguous:</p>

<pre><code>  optional&lt;optional&lt;int&gt;&gt; o(in_place, in_place, 1);
</code></pre>

<p>Additionally, when passing the tag types by value they decay from function
references to function pointers, and so are no longer usable where the
reference is needed as a tag.</p>

<p>Discussions on the reflectors and the CH 3 ballot comment suggest reverting
to simple tag types using structs, which have no surprising behaviour. There
have been no compelling arguments for keeping the function reference forms.</p>

<h2>Proposed Wording</h2>

<p>Originally <code>in_place_t</code> was defined in <code>&lt;optional&gt;</code>
and <code>in_place_type_t</code> and <code>in_place_index_t</code> was defined in <code>&lt;variant&gt;</code>, but
<code>in_place_index_t</code> is also needed in <code>&lt;any&gt;</code> as well. I propose putting all
of them in <code>&lt;utility&gt;</code> (where P0032R3 defined them) but it would be possible
to put them back in their original locations, and say that <code>&lt;any&gt;</code> also makes
<code>in_place_type_t</code> and <code>in_place_type</code> visible (similar to what we do for the
range access function in [iterator.range]).</p>

<p><a href="https://wg21.link/lwg2744">LWG 2744</a>, currently in Tentatively Ready status,
adds a SFINAE constraint to <code>any(ValueType&amp;&amp;)</code> related to the <code>in_place_type_t</code>
tag. That constraint needs to be changed to check <code>decay_t&lt;ValueType&gt;</code> not just
<code>ValueType</code>. A similar constraint is needed for the <code>variant(T&amp;&amp;)</code> constructor.</p>

<p>Edit the end of the synopsis in [utility]:</p>

<pre><code>  // <del>20.2.7,</del> in-place construction <del class="block">
  struct in_place_tag {
    in_place_tag() = delete;
  };
  using in_place_t = in_place_tag(&amp;)(unspecified );
  template &lt;class T&gt;
    using in_place_type_t = in_place_tag(&amp;)(unspecified &lt;T&gt;);
  template &lt;size_t I&gt;
    using in_place_index_t = in_place_tag(&amp;)(unspecified &lt;I&gt;);
  in_place_tag in_place(unspecified );
  template &lt;class T&gt;
    in_place_tag in_place(unspecified &lt;T&gt;);
  template &lt;size_t I&gt;
    in_place_tag in_place(unspecified &lt;I&gt;); </del> <ins class="block">
  struct in_place_t {
    explicit in_place_t() = default;
  };
  inline constexpr in_place_t in_place{};
  template &lt;class T&gt;
    struct in_place_type_t {
      explicit in_place_type_t() = default;
    };
  template &lt;class T&gt;
    inline constexpr in_place_type_t&lt;T&gt; in_place_type{};
  template &lt;size_t I&gt;
    struct in_place_index_t {
      explicit in_place_index_t() = default;
    };
  template &lt;size_t I&gt;
    inline constexpr in_place_index_t&lt;I&gt; in_place_index{};
  </ins>
</code></pre>

<p>Strike subclause 20.2.7 [utility.inplace] entirely.</p>

<blockquote><p><del> <strong>20.2.7.In-place construction [utility.inplace]</strong> </del></p>

<p><del> -1- The <code>in_place_t</code>, [...] </del></p>

<p><del> -2- <em>Remarks:</em> Calling [...] </del></p></blockquote>

<p>Modify 20.8.3.1 [any.cons] as indicated, <strong>after</strong> applying the resolution of
<a href="https://wg21.link/lwg2744">LWG 2744</a>:</p>

<pre><code>  template&lt;class ValueType&gt;
    any(ValueType&amp;&amp; value);
</code></pre>

<blockquote><p>-6- Let <code>T</code> be equal to <code>decay_t&lt;ValueType&gt;</code>.</p>

<p>-7- <em>Requires:</em> <code>T</code> shall satisfy the <code>CopyConstructible</code> requirements. If <code>is_copy_constructible_v&lt;T&gt;</code> is <code>false</code>, the program is ill-formed.</p>

<p>-8- <em>Effects:</em> Constructs an object of type <code>any</code> that contains an object of type <code>T</code> direct-initialized with <code>std::forward&lt;ValueType&gt;(value)</code>.</p>

<p>-9- <em>Remarks:</em> This constructor shall not participate in overload resolution if <code><ins>T</ins><del>decay_t&lt;ValueType&gt;</del></code> is the same type as <code>any</code> or if <code><ins>T</ins><del>ValueType</del></code> is a specialization of <code>in_place_type_t</code>.</p></blockquote>

<p>Modify 20.8.4 [any.nonmembers]:</p>

<blockquote><pre><code>  template &lt;class T, class ...Args&gt;
    any make_any(Args&amp;&amp; ...args);
</code></pre>

<p>-2-
<em>Effects:</em> Equivalent to: <code>return any(in_place<ins>_type</ins>&lt;T&gt;, std::forward&lt;Args&gt;(args)...);</code></p>

<pre><code>  template &lt;class T, class U, class ...Args&gt;
    any make_any(initializer_list&lt;U&gt; il, Args&amp;&amp; ...args);
</code></pre>

<p>-3-</p>

<p><em>Effects:</em> Equivalent to: <code>return any(in_place<ins>_type</ins>&lt;T&gt;, il, std::forward&lt;Args&gt;(args)...);</code></p></blockquote>

<p>Modify 20.7.2.1 [variant.ctor]:</p>

<pre><code>    template&lt;class T&gt; constexpr variant(T&amp;&amp; t) noexcept(see below );
</code></pre>

<blockquote><p>-12- Let <em>Tj</em> be a type that is determined as follows: build an imaginary function <em><code>FUN</code>(Ti)</em> for each alternative type <em>Ti</em>. The overload <em><code>FUN</code>(Tj)</em> selected by overload resolution for the expression <em><code>FUN</code></em><code>(std::forward&lt;T&gt;(t))</code> defines the alternative <em>Tj</em> which is the type of the contained value after construction.</p>

<p>-13- <em>Effects:</em> Initializes <code>*this</code> to hold the alternative type <em>Tj</em> and direct-initializes the contained value as if
direct-non-list-initializing it with <code>std::forward&lt;T&gt;(t)</code>.</p>

<p>-14- <em>Postconditions:</em> <code>holds_alternative&lt;Tj&gt;(*this)</code> is <code>true</code>.</p>

<p>-15- <em>Throws:</em> Any exception thrown by the initialization of the selected alternative <em>Tj</em>.</p>

<p>-16- <em>Remarks:</em> This function shall not participate in overload resolution unless <code>is_same_v&lt;decay_t&lt;T&gt;, variant&gt;</code> is <code>false</code>, <ins>unless <code>decay_t&lt;T&gt;</code> is neither a specialization of <code>in_place_type_t</code> nor a specialization of <code>in_place_index_t</code>,</ins> unless <code>is_constructible_v&lt;Tj, T&gt;</code> is <code>true</code>, and unless the expression <em><code>FUN</code></em><code>(std::forward&lt;T&gt;(t))</code> (with <em><code>FUN</code></em> being the above-mentioned set of imaginary functions) is well formed.</p>

<p>[<em>Note:</em></p></blockquote>

<pre><code>          variant&lt;string, string&gt; v("abc");
</code></pre>

<blockquote><p>is ill-formed, as both alternative types have an equally viable constructor for the argument. — <em>end note</em>]</p>

<p>-18- The expression inside <code>noexcept</code> is equivalent to <code>is_nothrow_constructible_v&lt;Tj , T&gt;</code>. If <em>Tj</em>’s selected
constructor is a constexpr constructor, this constructor shall be a constexpr constructor.</p></blockquote>

<h2>Acknowledgments</h2>

<p>Thanks to The Elf for implementing and testing these changes in libstdc++ and
reviewing this proposal. Thanks to Agustín Bergé for pointing out that the
constructors need to be constrained.</p>
</body></html>
