<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 1326: Missing&#47;wrong preconditions for pair and tuple functions</title>
<meta property="og:title" content="Issue 1326: Missing&#47;wrong preconditions for pair and tuple functions">
<meta property="og:description" content="C++ library issue. Status: Resolved">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue1326.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#Resolved">Resolved</a> status.</em></p>
<h3 id="1326"><a href="lwg-defects.html#1326">1326</a>. Missing&#47;wrong preconditions for <code>pair</code> and <code>tuple</code> functions</h3>
<p><b>Section:</b> 22.3.2 <a href="https://wg21.link/pairs.pair">[pairs.pair]</a>, 22.4.4.2 <a href="https://wg21.link/tuple.cnstr">[tuple.cnstr]</a> <b>Status:</b> <a href="lwg-active.html#Resolved">Resolved</a>
 <b>Submitter:</b> Daniel Kr&uuml;gler <b>Opened:</b> 2010-03-07 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View other</b> <a href="lwg-index-open.html#pairs.pair">active issues</a> in [pairs.pair].</p>
<p><b>View all other</b> <a href="lwg-index.html#pairs.pair">issues</a> in [pairs.pair].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Resolved">Resolved</a> status.</p>
<p><b>Discussion:</b></p>
<p>
There are several constructors and creation functions of std::tuple
that impose requirements on it's arguments, that are unnecessary
restrictive and don't match the intention for the supported argument
types. This is related to the fact that tuple is supposed to accept both
object types and lvalue-references and the usual MoveConstructible and
CopyConstructible requirements are bad descriptions for non-const
references. Some examples:
</p>

<ol style="list-style-type:lower-alpha">
<li>
<p>
22.4.4.2 <a href="https://wg21.link/tuple.cnstr">[tuple.cnstr]</a> before p.4 and p.8, resp.:
</p>

<blockquote><pre>
explicit tuple(const Types&amp;...);
</pre>
<blockquote><p>
4 <i>Requires:</i> Each type in <code>Types</code> shall be copy constructible.
</p></blockquote>

<pre>
tuple(const tuple&amp; u) = default;
</pre>
<blockquote><p>
8 <i>Requires:</i> Each type in <code>Types</code> shall satisfy the requirements of
<code>CopyConstructible</code> (Table 34).
</p></blockquote>
</blockquote>

<p>
A tuple that contains lvalue-references to non-const can never
satisfy the <code>CopyConstructible</code> requirements. <code>CopyConstructible</code>
requirements <i>refine</i> the <code>MoveConstructible</code> requirements and
this would require that these lvalue-references could bind
rvalues. But the core language does not allow that. Even, if we
would interpret that requirement as referring to the underlying
non-reference type, this requirement would be wrong as well,
because there is no reason to disallow a type such as
</p>

<blockquote><pre>
struct NoMoveNoCopy {
  NoMoveNoCopy(NoMoveNoCopy&amp;&amp;) = delete;
  NoMoveNoCopy(const NoMoveNoCopy&amp;) = delete;
  ...
}:
</pre></blockquote>

<p>
for the instantiation of <code>std::tuple&lt;NoMoveNoCopy&amp;&gt;</code> and
that of it's copy constructor.
</p>

<p>
A more reasonable requirement for this example would be to require that
"<code>is_constructible&lt;Ti, const Ti&amp;&gt;::value</code> shall
evaluate to true for all <code>Ti</code> in <code>Types</code>". In this case
the special reference-folding and const-merging rules of references
would make this well-formed in all cases. We could also add the further
constraint "if <code>Ti</code> is an object type, it shall satisfy the
<code>CopyConstructible</code> requirements", but this additional
requirement seems not really to help here. Ignoring it would only mean
that if a user would provide a curious object type <code>C</code> that
satisfies the <code>std::is_constructible&lt;C, const C&amp;&gt;</code>
test, but not the "<code>C</code> is <code>CopyConstructible</code>" test would
produce a <code>tuple&lt;C&gt;</code> that does not satisfy the
<code>CopyConstructible</code> requirements as well.
</p>
</li>

<li>
<p>
22.4.4.2 <a href="https://wg21.link/tuple.cnstr">[tuple.cnstr]</a> before p.6 and p.10, resp.:
</p>

<blockquote><pre>
template &lt;class... UTypes&gt;
explicit tuple(UTypes&amp;&amp;... u);
</pre>

<blockquote><p>
6 <i>Requires:</i> Each type in <code>Types</code> shall satisfy the
requirements of <code>MoveConstructible</code> (Table 33) from the
corresponding type in <code>UTypes</code>. <code>sizeof...(Types) ==
sizeof...(UTypes)</code>.
</p></blockquote>

<pre>
tuple(tuple&amp;&amp; u);
</pre>
<blockquote><p>
10 <i>Requires:</i> Each <code>type</code> in <code>Types</code> shall shall
satisfy the requirements of <code>MoveConstructible</code> (Table 33).
</p></blockquote>
</blockquote>

<p>
We have a similar problem as in (a): Non-const lvalue-references
are intended template arguments for <code>std::tuple</code>, but cannot satisfy
the <code>MoveConstructible</code> requirements. In this case the correct
requirements would be
</p>

<blockquote><p>
<code>is_constructible&lt;Ti, Ui&gt;::value</code> shall evaluate to true
for all <code>Ti</code> in <code>Types</code> and for all <code>Ui</code> in
<code>UTypes</code>
</p></blockquote>

<p>
and
</p>

<blockquote><p>
<code>is_constructible&lt;Ti, Ti&gt;::value</code> shall evaluate to true
for all <code>Ti</code> in <code>Types</code>
</p></blockquote>

<p>
respectively.
</p>
</li>
</ol>

<p>
Many <code>std::pair</code> member functions do not add proper requirements, e.g.
the default c'tor does not require anything. This is corrected within the
suggested resolution. Further-on the P/R has been adapted to the FCD numbering.
</p>

<p><i>[
2010-03-25 Daniel updated wording:
]</i></p>


<blockquote><p>
The issue became updated to fix some minor inconsistencies and to ensure a
similarly required fix for <code>std::pair</code>, which has the same specification
problem as <code>std::tuple</code>, since <code>pair</code> became extended to support
reference members as well.
</p></blockquote>

<p><i>[Original proposed resolution:]</i></p>

<ol>

<li>
<p>
Change 22.3.2 <a href="https://wg21.link/pairs.pair">[pairs.pair]</a>/1 as indicated <i>[The changes for the effects
elements are not normative changes, they just ensure
harmonization with existing wording style]</i>:
</p>

<blockquote><pre>
constexpr pair();
</pre>

<blockquote>
<p>
<ins><i>Requires:</i> <code>first_type</code> and <code>second_type</code> shall satisfy
the <code>DefaultConstructible</code> requirements.</ins>
</p>

<p>
1 <i>Effects:</i> <ins>Value-initializes <code>first</code> and
<code>second</code>.</ins><del>Initializes its members as if implemented: <code>pair()
: first(), second() { }</code>.</del>
</p>

</blockquote>
</blockquote>

</li>

<li>
<p>
Change 22.3.2 <a href="https://wg21.link/pairs.pair">[pairs.pair]</a>/2 as indicated:
</p>

<blockquote><pre>
pair(const T1&amp; x, const T2&amp; y);
</pre>

<blockquote>
<p>
<ins><i>Requires:</i> <code>is_constructible&lt;T1, const T1&amp;&gt;::value</code>
is <code>true</code> and <code>is_constructible&lt;T2, const T2&amp;&gt;::value</code>
is <code>true</code>.</ins>
</p>

<p>
2 <i>Effects:</i> The constructor initializes <code>first</code> with <code>x</code> and
<code>second</code> with <code>y</code>.
</p>

</blockquote>
</blockquote>

</li>

<li>
<p>
Change 22.3.2 <a href="https://wg21.link/pairs.pair">[pairs.pair]</a>/3 as indicated:
</p>

<blockquote><pre>
template&lt;class U, class V&gt; pair(U&amp;&amp; x, V&amp;&amp; y);
</pre>

<blockquote>
<p>
<ins><i>Requires:</i> <code>is_constructible&lt;first_type, U&gt;::value</code> is
<code>true</code> and <code>is_constructible&lt;second_type, V&gt;::value</code> is
<code>true</code>.</ins>
</p>

<p>
3 <i>Effects:</i> The constructor initializes <code>first</code> with
<code>std::forward&lt;U&gt;(x)</code> and <code>second</code> with
<code>std::forward&lt;V&gt;(y)</code>.
</p>

<p>
4 <i>Remarks:</i> If <code>U</code> is not implicitly convertible to
<code>first_type</code> or <code>V</code> is not implicitly convertible to
<code>second_type</code> this constructor shall not participate in overload
resolution.
</p>

</blockquote>
</blockquote>

</li>

<li>
<p>
Change 22.3.2 <a href="https://wg21.link/pairs.pair">[pairs.pair]</a>/5 as indicated <i>[The change in the effects
element should be non-normatively and is in compatible to the change suggestion
of <a href="lwg-defects.html#1324" title="Still too many implicit conversions for pair and  tuple (Status: Resolved)">1324</a><sup><a href="https://cplusplus.github.io/LWG/issue1324" title="Latest snapshot">(i)</a></sup>]</i>:
</p>

<blockquote><pre>
template&lt;class U, class V&gt; pair(const pair&lt;U, V&gt;&amp; p);
</pre>

<blockquote>
<p>
<ins><i>Requires:</i> <code>is_constructible&lt;first_type, const
U&amp;&gt;::value</code> is <code>true</code> and <code>is_constructible&lt;second_type,
const V&amp;&gt;::value</code> is <code>true</code>.</ins>
</p>

<p>
5 <i>Effects:</i> Initializes members from the corresponding members of the
argument<del>, performing implicit conversions as needed</del>.
</p>

</blockquote>
</blockquote>

</li>

<li>
<p>
Change 22.3.2 <a href="https://wg21.link/pairs.pair">[pairs.pair]</a>/6 as indicated:
</p>

<blockquote><pre>
template&lt;class U, class V&gt; pair(pair&lt;U, V&gt;&amp;&amp; p);
</pre>

<blockquote>
<p>
<ins><i>Requires:</i> <code>is_constructible&lt;first_type, U&gt;::value</code> is
<code>true</code> and <code>is_constructible&lt;second_type, V&gt;::value</code> is
<code>true</code>.</ins>
</p>

<p>
6 <i>Effects:</i> The constructor initializes <code>first</code> with
<code>std::<del>move</del><ins>forward&lt;U&gt;</ins>(p.first)</code> and
<code>second</code> with
<code>std::<del>move</del><ins>forward&lt;V&gt;</ins>(p.second)</code>.
</p>
</blockquote>
</blockquote>
</li>

<li>
<p>
Change 22.3.2 <a href="https://wg21.link/pairs.pair">[pairs.pair]</a>/7+8 as indicated [The deletion in the effects
element should be non-normatively]:
</p>

<blockquote><pre>
template&lt;class... Args1, class... Args2&gt;
  pair(piecewise_construct_t,
       tuple&lt;Args1...&gt; first_args, tuple&lt;Args2...&gt; second_args);
</pre>

<blockquote>
<p>
7 <i>Requires:</i> <ins><code>is_constructible&lt;first_type,
Args1...&gt;::value</code> is <code>true</code> and
<code>is_constructible&lt;second_type, Args2...&gt;::value</code> is
<code>true</code>.</ins> <del>All the types in <code>Args1</code> and <code>Args2</code>
shall be <code>CopyConstructible</code> (Table 35). <code>T1</code> shall be
constructible from <code>Args1</code>. <code>T2</code> shall be constructible from
<code>Args2</code>.</del>
</p>

<p>
8 <i>Effects:</i> The constructor initializes <code>first</code> with arguments of
types <code>Args1...</code> obtained by forwarding the elements of
<code>first_args</code> and initializes <code>second</code> with arguments of types
<code>Args2...</code> obtained by forwarding the elements of <code>second_args</code>.
<del>(Here, forwarding an element <code>x</code> of type <code>U</code> within a
<code>tuple</code> object means calling <code>std::forward&lt;U&gt;(x)</code>.)</del>
This form of construction, whereby constructor arguments for <code>first</code> and
<code>second</code> are each provided in a separate <code>tuple</code> object, is called
piecewise construction.
</p>

</blockquote>
</blockquote>

</li>

<li>
<p>
Change 22.3.2 <a href="https://wg21.link/pairs.pair">[pairs.pair]</a> before 12 as indicated:
</p>

<blockquote><pre>
pair&amp; operator=(pair&amp;&amp; p);
</pre>

<blockquote>
<p>
<ins><i>Requires:</i> <code>first_type</code> and <code>second_type</code> shall satisfy
the <code>MoveAssignable</code> requirements.</ins>
</p>

<p>
12 <i>Effects:</i> Assigns to <code>first</code> with <code>std::move(p.first)</code>
and to <code>second</code> with <code>std::move(p.second)</code>.
</p>

<p>
13 <i>Returns:</i> <code>*this</code>.
</p>

</blockquote>
</blockquote>

</li>

<li>
<p>
Change [pairs.pair] before 14 as indicated: [The heterogeneous usage
of MoveAssignable is actually not defined,
but the library uses it at several places, so we follow this tradition
until a better term has been agreed on. One
alternative could be to write "first_type shall be assignable from an
rvalue of U [..]"]
</p>

<blockquote><pre>
template&lt;class U, class V&gt; pair&amp; operator=(pair&lt;U, V&gt;&amp;&amp; p);
</pre>

<blockquote>

<p>
<ins><i>Requires:</i> <code>first_type</code> shall be <code>MoveAssignable</code> from
<code>U</code> and <code>second_type</code> shall be <code>MoveAssignable</code> from
<code>V</code>.</ins>
</p>

<p>
14 <i>Effects:</i> Assigns to <code>first</code> with <code>std::move(p.first)</code>
and to <code>second</code> with <code>std::move(p.second)</code>.
</p>

<p>
15 <i>Returns:</i> <code>*this</code>.
</p>

</blockquote>
</blockquote>

</li>

<li>
<p>
Change 22.4.4.2 <a href="https://wg21.link/tuple.cnstr">[tuple.cnstr]</a>/4+5 as indicated:
</p>

<blockquote><pre>
explicit tuple(const Types&amp;...);
</pre>

<blockquote>
<p>
4 <i>Requires:</i> <ins><code>is_constructible&lt;Ti, const
Ti&amp;&gt;::value == true</code> for e</ins><del>E</del>ach type
<ins><code>Ti</code></ins> in <code>Types</code><del> shall be copy
constructible</del>.
</p>

<p>
5 <i>Effects:</i> <del>Copy i</del><ins>I</ins>nitializes each element with the
value of the corresponding parameter.
</p>

</blockquote>
</blockquote>

</li>

<li>
<p>
Change 22.4.4.2 <a href="https://wg21.link/tuple.cnstr">[tuple.cnstr]</a>/6 as indicated:
</p>

<blockquote><pre>
template &lt;class... UTypes&gt;
explicit tuple(UTypes&amp;&amp;... u);
</pre>

<blockquote>
<p>
6 <i>Requires:</i> <ins><code>is_constructible&lt;Ti, Ui&gt;::value ==
true</code> for e</ins><del>E</del>ach type <ins><code>Ti</code></ins> in
<code>Types</code> <del>shall satisfy the requirements of
<code>MoveConstructible</code> (Table 33) from</del><ins>and for</ins> the
corresponding type <ins><code>Ui</code></ins> in <code>UTypes</code>.
<code>sizeof...(Types) == sizeof...(UTypes)</code>.
</p>

<p>
7 <i>Effects:</i> Initializes the elements in the <code>tuple</code> with the
corresponding value in <code>std::forward&lt;UTypes&gt;(u)</code>.
</p>

</blockquote>
</blockquote>
</li>

<li>
<p>
Change 22.4.4.2 <a href="https://wg21.link/tuple.cnstr">[tuple.cnstr]</a>/8+9 as indicated:
</p>

<blockquote><pre>
tuple(const tuple&amp; u) = default;
</pre>

<blockquote>
<p>
8 <i>Requires:</i> <ins><code>is_constructible&lt;Ti, const
Ti&amp;&gt;::value == true</code> for e</ins><del>E</del>ach type
<ins><code>Ti</code></ins> in <code>Types</code><del> shall satisfy the
requirements of <code>CopyConstructible</code>(Table 34)</del>.
</p>

<p>
9 <i>Effects:</i> <ins>Initializes</ins><del>Copy constructs</del> each element
of <code>*this</code> with the corresponding element of <code>u</code>.
</p>

</blockquote>
</blockquote>
</li>

<li>
<p>
Change 22.4.4.2 <a href="https://wg21.link/tuple.cnstr">[tuple.cnstr]</a>/10+11 as indicated:
</p>

<blockquote><pre>
tuple(tuple&amp;&amp; u);
</pre>

<blockquote>
<p>
10 <i>Requires:</i> <ins>Let <code>i</code> be in <code>[0, sizeof...(Types))</code> and
let <code>Ti</code> be the <code>i</code><sup><i>th</i></sup> type in <code>Types</code>.
Then <code>is_constructible&lt;Ti, Ti&gt;::value</code> shall be <code>true</code> for
all <code>i</code>.</ins> <del>Each type in <code>Types</code> shall shall satisfy the
requirements of <code>MoveConstructible</code> (Table 34)</del>.
</p>

<p>
11 <i>Effects:</i> <ins>For each <code>Ti</code> in <code>Types</code>, initializes the
<code>i</code><sup><i>th</i></sup></ins> <del>Move-constructs each</del> element of
<code>*this</code> with <del>the corresponding element of</del>
<ins><code>std::forward&lt;Ti&gt;(get&lt;i&gt;(</code></ins><code>u</code><ins><code>))</code></ins>.
</p>
</blockquote>
</blockquote>
</li>

<li>
<p>
Change 22.4.4.2 <a href="https://wg21.link/tuple.cnstr">[tuple.cnstr]</a>/15+16 as indicated:
</p>

<blockquote><pre>
template &lt;class... UTypes&gt; tuple(tuple&lt;UTypes...&gt;&amp;&amp; u);
</pre>

<blockquote>
<p>
15 <i>Requires:</i> <ins>Let <code>i</code> be in <code>[0, sizeof...(Types))</code>,
<code>Ti</code> be the <code>i</code><sup><i>th</i></sup> type in <code>Types</code>, and
<code>Ui</code> be the <code>i</code><sup><i>th</i></sup> type in <code>UTypes</code>. Then
<code>is_constructible&lt;Ti, Ui&gt;::value</code> shall be <code>true</code> for all
<code>i</code>.</ins> <del>Each type in <code>Types</code> shall shall satisfy the
requirements of <code>MoveConstructible</code> (Table 34) from the corresponding
type in <code>UTypes</code></del>. <code>sizeof...(Types) == sizeof...(UTypes)</code>.
</p>

<p>
16 <i>Effects:</i> <ins>For each type <code>Ti</code>, initializes the
<code>i</code><sup><i>th</i></sup></ins> <del>Move-constructs each</del> element of
<code>*this</code> with <del>the corresponding element of</del>
<ins><code>std::forward&lt;Ui&gt;(get&lt;i&gt;(</code></ins><code>u</code><ins><code>))</code></ins>.
</p>

</blockquote>
</blockquote>

</li>

<li>
<p>
Change 22.4.4.2 <a href="https://wg21.link/tuple.cnstr">[tuple.cnstr]</a>/19+20 as indicated:
</p>

<blockquote><pre>
template &lt;class U1, class U2&gt; tuple(pair&lt;U1, U2&gt;&amp;&amp; u);
</pre>

<blockquote>
<p>
19 <i>Requires:</i> <ins><code>is_constructible&lt;T1, U1&gt;::value ==
true</code> for <code>t</code></ins><del><code>T</code></del>he first type
<ins><code>T1</code></ins> in <code>Types</code> <del>shall shall satisfy the
requirements of <code>MoveConstructible</code>(Table 33) from
<code>U1</code></del> and <ins><code>is_constructible&lt;T2, U2&gt;::value ==
true</code> for</ins> the second type <ins><code>T2</code></ins> in
<code>Types</code> <del>shall be move-constructible from <code>U2</code></del>.
<code>sizeof...(Types) == 2</code>.
</p>

<p>
20 <i>Effects:</i> <ins>Initializes</ins><del>Constructs</del> the first
element with
<code>std::<ins>forward&lt;U1&gt;</ins><del>move</del>(u.first)</code> and
the second element with
<code>std::<ins>forward&lt;U2&gt;</ins><del>move</del>(u.second)</code>.
</p>

</blockquote>
</blockquote>
</li>

<li>
<p>
Change 22.4.5 <a href="https://wg21.link/tuple.creation">[tuple.creation]</a>/9-16 as indicated:
</p>

<blockquote><pre>
template &lt;class... TTypes, class... UTypes&gt;
tuple&lt;TTypes..., UTypes...&gt; tuple_cat(const tuple&lt;TTypes...&gt;&amp; t, const tuple&lt;UTypes...&gt;&amp; u);
</pre>

<blockquote>
<p>
9 <i>Requires:</i> <ins><code>is_constructible&lt;Ti, const
Ti&amp;&gt;::value == true</code> for each type <code>Ti</code></ins><del>All
the types</del> in <code>TTypes</code> <del>shall be
<code>CopyConstructible</code> (Table 34)</del>.
<ins><code>is_constructible&lt;Ui, const Ui&amp;&gt;::value == true</code>
for each type <code>Ui</code></ins><del>All the types</del> in
<code>UTypes</code> <del>shall be <code>CopyConstructible</code> (Table
34)</del>.
</p>

<p>
10 <i>Returns:</i> A <code>tuple</code> object constructed by
<ins>initializing</ins><del>copy constructing</del> its first
<code>sizeof...(TTypes)</code> elements from the corresponding elements of
<code>t</code> and <ins>initializing</ins><del>copy constructing</del> its
last <code>sizeof...(UTypes)</code> elements from the corresponding elements
of <code>u</code>.
</p>
</blockquote>

<pre>
template &lt;class... TTypes, class... UTypes&gt;
tuple&lt;TTypes..., UTypes...&gt; tuple_cat(tuple&lt;TTypes...&gt;&amp;&amp; t, const tuple&lt;UTypes...&gt;&amp; u);
</pre>

<blockquote>
<p>
11 <i>Requires:</i> <ins>Let <code>i</code> be in <code>[0, sizeof...(TTypes))</code>,
<code>Ti</code> be the <code>i</code><sup><i>th</i></sup> type in <code>Types</code>,
<code>j</code> be in <code>[0, sizeof...(UTypes))</code>, and <code>Uj</code> be the
<code>j</code><sup><i>th</i></sup> type in <code>UTypes</code>.
<code>is_constructible&lt;Ti, Ti&gt;::value</code> shall be <code>true</code> for each
type <code>Ti</code> and <code>is_constructible&lt;Uj, const Uj&amp;&gt;::value</code>
shall be <code>true</code> for each type <code>Uj</code></ins> <del>All the types in
<code>TTypes</code> shall be <code>MoveConstructible</code> (Table 34). All the types in
<code>UTypes</code> shall be <code>CopyConstructible</code> (Table 35)</del>.
</p>

<p>
12 <i>Returns:</i> A <code>tuple</code> object constructed by <ins>initializing the
<code>i</code><sup><i>th</i></sup> element with
<code>std::forward&lt;Ti&gt;(get&lt;i&gt;(t))</code> for all <code>Ti</code> in
<code>TTypes</code> and initializing the
<code>(j+sizeof...(TTypes))</code><sup><i>th</i></sup> element with
<code>get&lt;j&gt;(u)</code> for all <code>Uj</code> in <code>UTypes</code>.</ins> <del>move
constructing its first <code>sizeof...(TTypes)</code> elements from the
corresponding elements of <code>t</code> and copy constructing its last
<code>sizeof...(UTypes)</code> elements from the corresponding elements of
<code>u</code></del>.
</p>
</blockquote>

<pre>
template &lt;class... TTypes, class... UTypes&gt;
tuple&lt;TTypes..., UTypes...&gt; tuple_cat(const tuple&lt;TTypes...&gt;&amp; t, tuple&lt;UTypes...&gt;&amp;&amp; u);
</pre>

<blockquote>
<p>
13 <i>Requires:</i> <ins>Let <code>i</code> be in <code>[0, sizeof...(TTypes))</code>,
<code>Ti</code> be the <code>i</code><sup><i>th</i></sup> type in <code>Types</code>,
<code>j</code> be in <code>[0, sizeof...(UTypes))</code>, and <code>Uj</code> be the
<code>j</code><sup><i>th</i></sup> type in <code>UTypes</code>.
<code>is_constructible&lt;Ti, const Ti&amp;&gt;::value</code> shall be <code>true</code>
for each type <code>Ti</code> and <code>is_constructible&lt;Uj, Uj&gt;::value</code>
shall be <code>true</code> for each type <code>Uj</code></ins> <del>All the types in
<code>TTypes</code> shall be <code>CopyConstructible</code> (Table 35). All the types in
<code>UTypes</code> shall be <code>MoveConstructible</code> (Table 34)</del>.
</p>

<p>
14 <i>Returns:</i> A <code>tuple</code> object constructed by <ins>initializing the
<code>i</code><sup><i>th</i></sup> element with <code>get&lt;i&gt;(t)</code> for each
type <code>Ti</code> and initializing the
<code>(j+sizeof...(TTypes))</code><sup><i>th</i></sup> element with
<code>std::forward&lt;Uj&gt;(get&lt;j&gt;(u))</code> for each type <code>Uj</code></ins>
<del>copy constructing its first <code>sizeof...(TTypes)</code> elements from the
corresponding elements of <code>t</code> and move constructing its last
<code>sizeof...(UTypes)</code> elements from the corresponding elements of
<code>u</code></del>.
</p>
</blockquote>

<pre>
template &lt;class... TTypes, class... UTypes&gt;
tuple&lt;TTypes..., UTypes...&gt; tuple_cat(tuple&lt;TTypes...&gt;&amp;&amp; t, tuple&lt;UTypes...&gt;&amp;&amp; u);
</pre>

<blockquote>
<p>
15 <i>Requires:</i> <ins>Let <code>i</code> be in <code>[0, sizeof...(TTypes))</code>,
<code>Ti</code> be the <code>i</code><sup><i>th</i></sup> type in <code>Types</code>,
<code>j</code> be in <code>[0, sizeof...(UTypes))</code>, and <code>Uj</code> be the
<code>j</code><sup><i>th</i></sup> type in <code>UTypes</code>.
<code>is_constructible&lt;Ti, Ti&gt;::value</code> shall be <code>true</code> for each
type <code>Ti</code> and <code>is_constructible&lt;Uj, Uj&gt;::value</code> shall be
<code>true</code> for each type <code>Uj</code></ins> <del>All the types in
<code>TTypes</code> shall be <code>MoveConstructible</code> (Table 34). All the types in
<code>UTypes</code> shall be <code>MoveConstructible</code> (Table 34)</del>.
</p>

<p>
16 <i>Returns:</i> A <code>tuple</code> object constructed by <ins>initializing the
<code>i</code><sup><i>th</i></sup> element with
<code>std::forward&lt;Ti&gt;(get&lt;i&gt;(t))</code> for each type <code>Ti</code> and
initializing the <code>(j+sizeof...(TTypes))</code><sup><i>th</i></sup> element with
<code>std::forward&lt;Uj&gt;(get&lt;j&gt;(u))</code> for each type <code>Uj</code></ins>
<del>move constructing its first <code>sizeof...(TTypes)</code> elements from the
corresponding elements of <code>t</code> and move constructing its last
<code>sizeof...(UTypes)</code> elements from the corresponding elements of
<code>u</code></del>.
</p>
</blockquote>
</blockquote>
</li>
</ol>


<p><i>[
2010-10-24 Daniel adds:
]</i></p>


<blockquote><p>
Accepting <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3140.html">n3140</a> 
would solve this issue.
</p></blockquote>


<p id="res-1326"><b>Proposed resolution:</b></p>
<p>
See <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3140.html">n3140</a>.
</p>





</body>
</html>
