<html><head><title>Constexpr Library Additions v3: utilities</title><style type="text/css">ol{margin:0;padding:0}.c2{font-size:9pt;background-color:#b6d7a8;font-weight:bold}.c7{max-width:468pt;background-color:#ffffff;padding:72pt 72pt 72pt 72pt}.c0{height:11pt;direction:ltr}.c12{background-color:#ea9999;text-decoration:line-through}.c11{color:inherit;text-decoration:inherit}.c10{color:#000099;text-decoration:underline}.c14{color:#1155cc;text-decoration:underline}.c9{font-size:18pt}.c1{direction:ltr}.c13{background-color:#b6d7a8}.c3{font-weight:bold}.c5{font-style:italic}.c4{font-size:9pt}.c6{font-size:14pt}.c8{font-size:24pt}.title{padding-top:24pt;line-height:1.15;text-align:left;color:#000000;font-size:36pt;font-family:"Arial";font-weight:bold;padding-bottom:6pt}.subtitle{padding-top:18pt;line-height:1.15;text-align:left;color:#666666;font-style:italic;font-size:24pt;font-family:"Georgia";padding-bottom:4pt}li{color:#000000;font-size:11pt;font-family:"Arial"}p{color:#000000;font-size:11pt;margin:0;font-family:"Arial"}h1{padding-top:24pt;line-height:1.15;text-align:left;color:#000000;font-size:24pt;font-family:"Arial";font-weight:bold;padding-bottom:6pt}h2{padding-top:18pt;line-height:1.15;text-align:left;color:#000000;font-size:18pt;font-family:"Arial";font-weight:bold;padding-bottom:4pt}h3{padding-top:14pt;line-height:1.15;text-align:left;color:#000000;font-size:14pt;font-family:"Arial";font-weight:bold;padding-bottom:4pt}h4{padding-top:12pt;line-height:1.15;text-align:left;color:#000000;font-size:12pt;font-family:"Arial";font-weight:bold;padding-bottom:2pt}h5{padding-top:11pt;line-height:1.15;text-align:left;color:#000000;font-size:11pt;font-family:"Arial";font-weight:bold;padding-bottom:2pt}h6{padding-top:10pt;line-height:1.15;text-align:left;color:#000000;font-size:10pt;font-family:"Arial";font-weight:bold;padding-bottom:2pt}</style></head><body class="c7"><p class="c1"><span class="c9 c3">Constexpr Library Additions:</span><span class="c9 c3">&nbsp;</span><span class="c9 c3">utilities, v3</span></p><p class="c0"><span class="c3 c8"></span></p><p class="c1"><span>ISO/IEC JTC1 SC22 WG21 N3471 = 12-0161</span></p><p class="c1"><span>2012-10-18</span></p><p class="c1"><span>Benjamin Kosnik, </span><span class="c14"><a class="c11" href="mailto:bkoz@redhat.com">bkoz@redhat.com</a></span></p><p class="c1"><span>Daniel Krugler, </span><span class="c10"><a class="c11" href="mailto:daniel.kruegler@googlemail.com">daniel.kruegler@googlemail.com</a></span></p><p class="c0"><span></span></p><p class="c1"><span class="c3">Addresses</span><span class="c3 c6">: </span><span>LWG 2013</span></p><p class="c0"><span></span></p><p class="c0"><span></span></p><p class="c1"><span class="c3 c6">Introduction</span></p><p class="c0"><span class="c9 c3"></span></p><p class="c1"><span>This paper details use of the ISO C++0x constexpr feature, as initially introduced in &ldquo;Generalized Constant Expressions &mdash; Revision 5&rdquo; (N2235) and incorporating all other subsequent changes as per ISO C++ draft N3376. It is the first revision of N3305. Several CWG issues have also influenced the language with respect to constexpr: see issues 1099, 1125, 1194, 1195, 1197, 1198, 1199 and c++-std-core postings number 17890 and 17912. For pair and tuple, see N3140. Additional implementation experience, and subsequent changes to the core language have motivated the following changes and additions to the library specification. </span></p><p class="c0"><span></span></p><h3 class="c1"><span class="c3 c6">Proposed Changes</span></h3><p class="c0"><span></span></p><p class="c1"><span>A list of additional places in Chapters 18 Support or 20 Utilities that can exploit the constexpr language feature is below. For the changes listed, the new text is put in place</span><span class="c3 c5">&nbsp;</span><span class="c3 c13">in bold and green</span><span>&nbsp;with the older text it is replacing </span><span class="c12">struckthrough in red</span><span>.</span></p><p class="c0"><span></span></p><p class="c1"><span class="c3">01. &lt;initializer_list&gt;</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span>Add the following:</span></p><p class="c0"><span></span></p><p class="c1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- Mark class template initializer_list&rsquo;s default constructor and member functions &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p><p class="c1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; size, begin, and end constexpr.</span></p><p class="c0"><span></span></p><p class="c1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- Mark function templates begin and end constexpr.</span></p><p class="c0"><span></span></p><p class="c1"><span class="c3">02. &lt;utility&gt;</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span>Add the following:</span></p><p class="c1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p><p class="c1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- Mark function templates forward, move, and move_if_noexcept constexpr.</span></p><p class="c1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- Mark non-defaulted constructors constexpr (It is important th</span><span>at &nbsp;</span></p><p class="c1"><span>&nbsp; &nbsp; &nbsp; &nbsp;std::pair&lt;std::string, int&gt;&rsquo;s copy constructor is still well-formed)</span><span>. </span><span class="c5">The intent is </span></p><p class="c1"><span class="c5">&nbsp; &nbsp; &nbsp; &nbsp;</span><span class="c5">that all defaulted </span><span class="c5">copy/move constructors are constexpr, if they can </span></p><p class="c1"><span class="c5">&nbsp; &nbsp; &nbsp; &nbsp;be constexpr.</span></p><p class="c1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- Mark pair comparison operators ==, !=, &gt;, &gt;=, &lt;, &lt;= constexpr.</span></p><p class="c1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- Mark function template make_pair constexpr</span></p><p class="c0"><span></span></p><p class="c1"><span class="c3">03. &lt;tuple&gt;</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span>Add the following:</span></p><p class="c0"><span></span></p><p class="c1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- Mark </span><span>non-defaulted tuple constructors</span><span>&nbsp;constexpr (It is important that std::tuple&lt;std::string&gt;</span><span>&rsquo; copy constructor is still well-formed)</span><span>. </span><span class="c5">The intent is that all defaulted copy/move constructors are constexpr, if they can be constexpr.</span></p><p class="c1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- Make instances of function template get constexpr</span></p><p class="c1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- Mark tuple_cat and make_tuple constexpr</span></p><p class="c1"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- Mark tuple comparison operators ==, !=, &gt;, &gt;=, &lt;, &lt;= constexpr</span></p><p class="c0"><span class="c3"></span></p><p class="c0"><span></span></p><p class="c1"><span class="c3 c6">Proposed wording</span></p><p class="c0"><span></span></p><p class="c1"><span class="c3">a) Modify 18.9 [support.initlist]</span><span class="c3">&nbsp;</span><span class="c3">as follows:</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;initializer_list() noexcept;</span></p><p class="c1"><span class="c4">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;size_t size() const noexcept;</span></p><p class="c1"><span class="c4">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;const E* begin() const noexcept;</span></p><p class="c1"><span class="c4">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;const E* end() const noexcept;</span></p><p class="c0"><span></span></p><p class="c1"><span class="c3">b) Modify 18.9.1 [support.initlist.cons]</span><span class="c3">&nbsp;</span><span class="c3">as follows:</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;initializer_list() noexcept;</span></p><p class="c0"><span></span></p><p class="c1"><span class="c3">c) Modify 18.9.2 [support.initlist.access]</span><span class="c3">&nbsp;</span><span class="c3">as follows:</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;const E* begin() const noexcept;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;const E* end() const noexcept;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;size_t size() const noexcept;</span></p><p class="c0"><span></span></p><p class="c1"><span class="c3">d) Modify 18.9.3 [support.initlist.range]</span><span class="c3">&nbsp;</span><span class="c3">as follows:</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span class="c4">template&lt;class E&gt; </span><span class="c2">constexpr</span><span class="c4">&nbsp;const E* begin(initializer_list&lt;E&gt; il) noexcept;</span></p><p class="c0"><span></span></p><p class="c1"><span class="c4">template&lt;class E&gt; </span><span class="c2">constexpr</span><span class="c4">&nbsp;const E* end(initializer_list&lt;E&gt; il) noexcept;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c3">e) Modify 20.2 [utility] as follows:</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span class="c4">// 20.2.3, forward/move:</span></p><p class="c1"><span class="c4">template &lt;class T&gt; </span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;T&amp;&amp; forward(typename remove_reference&lt;T&gt;::type&amp; t) noexcept;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class T&gt; </span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;T&amp;&amp; forward(typename remove_reference&lt;T&gt;::type&amp;&amp; t) noexcept;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class T&gt; </span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;typename remove_reference&lt;T&gt;::type&amp;&amp; move(T&amp;&amp;) noexcept;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class T&gt; </span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;typename conditional&lt;</span></p><p class="c1"><span class="c4">!is_nothrow_move_constructible&lt;T&gt;::value &amp;&amp; is_copy_constructible&lt;T&gt;::value,</span></p><p class="c1"><span class="c4">const T&amp;, T&amp;&amp;&gt;::type move_if_noexcept(T&amp; x) noexcept;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">&hellip;.</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">// 20.3.3, pair specialized algorithms:</span></p><p class="c1"><span class="c4">template &lt;class T1, class T2&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator==(const pair&lt;T1,T2&gt;&amp;, const pair&lt;T1,T2&gt;&amp;);</span></p><p class="c1"><span class="c4">template &lt;class T1, class T2&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator&lt; (const pair&lt;T1,T2&gt;&amp;, const pair&lt;T1,T2&gt;&amp;);</span></p><p class="c1"><span class="c4">template &lt;class T1, class T2&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator!=(const pair&lt;T1,T2&gt;&amp;, const pair&lt;T1,T2&gt;&amp;);</span></p><p class="c1"><span class="c4">template &lt;class T1, class T2&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator&gt; (const pair&lt;T1,T2&gt;&amp;, const pair&lt;T1,T2&gt;&amp;);</span></p><p class="c1"><span class="c4">template &lt;class T1, class T2&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator&gt;=(const pair&lt;T1,T2&gt;&amp;, const pair&lt;T1,T2&gt;&amp;);</span></p><p class="c1"><span class="c4">template &lt;class T1, class T2&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator&lt;=(const pair&lt;T1,T2&gt;&amp;, const pair&lt;T1,T2&gt;&amp;);</span></p><p class="c1"><span class="c4">template &lt;class T1, class T2&gt;</span></p><p class="c1"><span class="c4">void swap(pair&lt;T1,T2&gt;&amp; x, pair&lt;T1,T2&gt;&amp; y)</span></p><p class="c1"><span class="c4">template &lt;class T1, class T2&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c3 c4">&nbsp;</span><span class="c5 c4">see below</span><span class="c4">&nbsp;make_pair(T1&amp;&amp;, T2&amp;&amp;);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">&hellip;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template&lt;size_t I, class T1, class T2&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;typename tuple_element&lt;I, std::pair&lt;T1, T2&gt; &gt;::type&amp; </span></p><p class="c1"><span class="c4">get(std::pair&lt;T1, T2&gt;&amp;) noexcept;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template&lt;size_t I, class T1, class T2&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;typename tuple_element&lt;I, std::pair&lt;T1, T2&gt; &gt;::type&amp;&amp; </span></p><p class="c1"><span class="c4">get(std::pair&lt;T1, T2&gt;&amp;&amp;) noexcept;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template&lt;size_t I, class T1, class T2&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;const typename tuple_element&lt;I, std::pair&lt;T1, T2&gt; &gt;::type&amp; </span></p><p class="c1"><span class="c4">get(const std::pair&lt;T1, T2&gt;&amp;) noexcept;</span></p><p class="c0"><span class="c4"></span></p><p class="c0"><span></span></p><p class="c1"><span class="c3">f) Modify 20.2.3 [forward] as follows:</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span class="c4">template &lt;class T&gt; </span><span class="c2">constexpr</span><span class="c4">&nbsp; T&amp;&amp; forward(typename remove_reference&lt;T&gt;::type&amp; t) noexcept;</span></p><p class="c1"><span class="c4">template &lt;class T&gt; </span><span class="c2">constexpr</span><span class="c4">&nbsp; T&amp;&amp; forward(typename remove_reference&lt;T&gt;::type&amp;&amp; t) noexcept;</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span class="c4">template &lt;class T&gt; </span><span class="c2">constexpr</span><span class="c4">&nbsp;typename remove_reference&lt;T&gt;::type&amp;&amp; move(T&amp;&amp; t) noexcept;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class T&gt; </span><span class="c2">constexpr</span><span class="c4">&nbsp;typename conditional&lt;</span></p><p class="c1"><span class="c4">!is_nothrow_move_constructible&lt;T&gt;::value &amp;&amp; is_copy_constructible&lt;T&gt;::value,</span></p><p class="c1"><span class="c4">const T&amp;, T&amp;&amp;&gt;::type move_if_noexcept(T&amp; x) noexcept;</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span class="c3">g</span><span class="c3">) Modify 20.3.</span><span class="c3">2 [pairs.pair]</span><span class="c3">&nbsp;as follows:</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span class="c4">pair(const pair&amp;) = default;</span></p><p class="c1"><span class="c4">pair(pair&amp;&amp;) = default;</span></p><p class="c1"><span class="c4">constexpr pair();</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;pair(const T1&amp; x, const T2&amp; y);</span></p><p class="c1"><span class="c4">template&lt;class U, class V&gt; </span><span class="c2">constexpr</span><span class="c4">&nbsp;pair(U&amp;&amp; x, V&amp;&amp; y);</span></p><p class="c1"><span class="c4">template&lt;class U, class V&gt; </span><span class="c2">constexpr</span><span class="c4">&nbsp;pair(const pair&lt;U, V&gt;&amp; p);</span></p><p class="c1"><span class="c4">template&lt;class U, class V&gt; </span><span class="c2">constexpr</span><span class="c4">&nbsp;pair(pair&lt;U, V&gt;&amp;&amp; p);</span></p><p class="c1"><span>...</span></p><p class="c0"><span></span></p><p class="c1"><span class="c3 c4">and</span><span class="c4">&nbsp;modify the following prototype declarations before paragraph 4, 6, 9, and 12 accordingly.</span></p><p class="c0"><span></span></p><p class="c1"><span class="c3">h) Add to 20.3.2 [pairs.pair] &nbsp;after paragraph 1 as follows:</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span class="c2">The defaulted move and copy constructor, respectively, of pair shall be a constexpr function if and only if all required element-wise initializations for copy and move, respectively, would satisfy the requirements for a constexpr function.</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c3">i</span><span class="c3">) Modify 20.3.3 [pairs.spec]</span><span class="c3">&nbsp;</span><span class="c3">as follows:</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span class="c4">template &lt;class T1, class T2&gt;</span></p><p class="c1"><span class="c4">&nbsp;</span><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator==(const pair&lt;T1, T2&gt;&amp; x, const pair&lt;T1, T2&gt;&amp; y);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class T1, class T2&gt;</span></p><p class="c1"><span class="c4">&nbsp;</span><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator&lt;(const pair&lt;T1, T2&gt;&amp; x, const pair&lt;T1, T2&gt;&amp; y);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class T1, class T2&gt;</span></p><p class="c1"><span class="c4">&nbsp;</span><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator!=(const pair&lt;T1, T2&gt;&amp; x, const pair&lt;T1, T2&gt;&amp; y);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class T1, class T2&gt;</span></p><p class="c1"><span class="c4">&nbsp;</span><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator&gt;(const pair&lt;T1, T2&gt;&amp; x, const pair&lt;T1, T2&gt;&amp; y);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class T1, class T2&gt;</span></p><p class="c1"><span class="c4">&nbsp;</span><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator&gt;=(const pair&lt;T1, T2&gt;&amp; x, const pair&lt;T1, T2&gt;&amp; y);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class T1, class T2&gt;</span></p><p class="c1"><span class="c4">&nbsp;</span><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator&lt;=(const pair&lt;T1, T2&gt;&amp; x, const pair&lt;T1, T2&gt;&amp; y);</span></p><p class="c1"><span class="c4">&hellip;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class T1, class T2&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;pair&lt;V1, V2&gt; make_pair(T1&amp;&amp; x, T2&amp;&amp; y)</span></p><p class="c0"><span class="c4"></span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c3">j) Modify 20.3.4 [pair.astuple] as follows:</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template&lt;size_t I, class T1, class T2&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;typename tuple_element&lt;I, std::pair&lt;T1, T2&gt; &gt;::type&amp; </span></p><p class="c1"><span class="c4">get(pair&lt;T1, T2&gt;&amp;) noexcept;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template&lt;size_t I, class T1, class T2&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;const typename tuple_element&lt;I, std::pair&lt;T1, T2&gt; &gt;::type&amp; </span></p><p class="c1"><span class="c4">get(const pair&lt;T1, T2&gt;&amp;) noexcept;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template&lt;size_t I, class T1, class T2&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;typename tuple_element&lt;I, std::pair&lt;T1, T2&gt; &gt;::type&amp;&amp; </span></p><p class="c1"><span class="c4">get(pair&lt;T1, T2&gt;&amp;&amp;) noexcept;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c3">k) Modify 20.4.1 [tuple.general] as follows:</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;size_t I, class... types&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;typename tuple_element&lt;I, tuple&lt;Types...&gt; &gt;::type&amp; </span></p><p class="c1"><span class="c4">get(tuple&lt;Types...&gt;&amp;) noexcept;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;size_t I, class... types&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;typename tuple_element&lt;I, tuple&lt;Types...&gt; &gt;::type &amp;&amp; </span></p><p class="c1"><span class="c4">get(tuple&lt;Types...&gt;&amp;&amp;) noexcept;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;size_t I, class... types&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;typename tuple_element&lt;I, tuple&lt;Types...&gt; &gt;::type const&amp; </span></p><p class="c1"><span class="c4">get(const tuple&lt;Types...&gt;&amp;) noexcept;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class... Types&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;tuple&lt;VTypes ...&gt; </span></p><p class="c1"><span class="c4">make_tuple(Types&amp;&amp;...);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class... Tuples&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;tuple&lt;Ctypes ...&gt; </span></p><p class="c1"><span class="c4">tuple_cat(Tuples&amp;&amp;...);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template&lt;class... TTypes, class... UTypes&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator==(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);</span></p><p class="c1"><span class="c4">template&lt;class... TTypes, class... UTypes&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator&lt;(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);</span></p><p class="c1"><span class="c4">template&lt;class... TTypes, class... UTypes&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator!=(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);</span></p><p class="c1"><span class="c4">template&lt;class... TTypes, class... UTypes&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator&gt;(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);</span></p><p class="c1"><span class="c4">template&lt;class... TTypes, class... UTypes&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator&lt;=(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);</span></p><p class="c1"><span class="c4">template&lt;class... TTypes, class... UTypes&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator&gt;=(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c3">l</span><span class="c3">) Modify 20.4.2 </span><span class="c3">[tuple.tuple] </span><span class="c3">as follows:</span></p><p class="c0"><span class="c3 c4"></span></p><p class="c1"><span class="c4">constexpr tuple();</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">explicit </span><span class="c2">constexpr</span><span class="c4">&nbsp;tuple(const Types&amp;...);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class... UTypes&gt;</span></p><p class="c1"><span class="c4">explicit </span><span class="c2">constexpr</span><span class="c4">&nbsp;tuple(UTypes&amp;&amp;...)</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">tuple(const tuple&amp;) = default;</span></p><p class="c1"><span class="c4">tuple(tuple&amp;&amp;) = default;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class... UTypes&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;tuple(const tuple&lt;UTypes...&gt;&amp;);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class... UTypes&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;tuple(tuple&lt;UTypes...&gt;&amp;&amp;);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class U1, class U2&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;tuple(const pair&lt;U1, U2&gt;&amp;); // iff sizeof...(Types) == 2</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span class="c4">template &lt;class U1, class U2&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;tuple(pair&lt;U1, U2&gt;&amp;&amp;); // iff sizeof...(Types) == 2</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span class="c3">m</span><span class="c3">) Modify 20.4.2.1 [tuple.cnstr]</span><span class="c3">&nbsp;</span><span class="c3">as follows:</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span class="c4">explicit </span><span class="c2">constexpr</span><span class="c4">&nbsp;tuple(const Types&amp;...);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class... UTypes&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;tuple(const tuple&lt;UTypes...&gt;&amp;);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class... UTypes&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;tuple(tuple&lt;UTypes...&gt;&amp;&amp;);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class U1, class U2&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;tuple(const pair&lt;U1, U2&gt;&amp;); // iff sizeof...(Types) == 2</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span class="c4">template &lt;class U1, class U2&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;tuple(pair&lt;U1, U2&gt;&amp;&amp;); // iff sizeof...(Types) == 2</span></p><p class="c0"><span></span></p><p class="c1"><span class="c3">n) Add to 20.4.2.1 [tuple.cnstr] &nbsp;after paragraph 1 as follows:</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span class="c2">&nbsp;The defaulted move and copy constructor, respectively, of tuple shall be a constexpr function if and only if all required element-wise initializations for copy and move, respectively, would satisfy the requirements for a constexpr function. The defaulted move and copy constructor of tuple&lt;&gt; shall be constexpr functions.</span></p><p class="c0"><span class="c3"></span></p><p class="c1"><span class="c3">o</span><span class="c3">) Modify 20.4.2.6 [tuple.elem] as follows:</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;size_t I, class... Types&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;typename tuple_element&lt;I, tuple&lt;Types...&gt; &gt;::type &amp; get(tuple&lt;Types...&gt;&amp; t) noexcept;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;size_t I, class... types&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;typename tuple_element&lt;I, tuple&lt;Types...&gt; &gt;::type&amp;&amp; get(tuple&lt;Types...&gt;&amp;&amp; t) noexcept;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;size_t I, class... Types&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;typename tuple_element&lt;I, tuple&lt;Types...&gt; &gt;::type const&amp; get(const tuple&lt;Types...&gt;&amp; t) noexcept;</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c3">p) Modify 20.4.2.4 [tuple.creation] as follows:</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template&lt;class... Types&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;tuple&lt;VTypes ...&gt; </span></p><p class="c1"><span class="c4">make_tuple(Types&amp;&amp;... t);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template &lt;class... Tuples&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;tuple&lt;CTypes ...&gt; </span></p><p class="c1"><span class="c4">tuple_cat(Tuples&amp;&amp;... tpls);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c3">q) Modify 20.4.2.7 [tuple.rel] as follows:</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template&lt;class... TTypes, class... UTypes&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator==(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template&lt;class... TTypes, class... UTypes&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator&lt;(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template&lt;class... TTypes, class... UTypes&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator!=(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template&lt;class... TTypes, class... UTypes&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator&gt;(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template&lt;class... TTypes, class... UTypes&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator&lt;=(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);</span></p><p class="c0"><span class="c4"></span></p><p class="c1"><span class="c4">template&lt;class... TTypes, class... UTypes&gt;</span></p><p class="c1"><span class="c2">constexpr</span><span class="c4">&nbsp;bool operator&gt;=(const tuple&lt;TTypes...&gt;&amp;, const tuple&lt;UTypes...&gt;&amp;);</span></p><p class="c0"><span class="c4"></span></p><p class="c0"><span class="c4"></span></p><p class="c0"><span></span></p><p class="c1"><span class="c3 c6">Acknowledgments</span></p><p class="c0"><span></span></p><p class="c1"><span>Many thanks to Daniel Kr&uuml;gler, Alisdair Meredith, &nbsp;Jason Merrill, Paolo Carlini, and Jonathan Wakely for reviewing this document and providing assistance.</span></p></body></html>