<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />

<title>Improving Pair and Tuple (Revision 3)</title>

<style type="text/css">
  p {text-align:justify}
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  blockquote.note
  {
   background-color:#E0E0E0;
   padding-left: 15px;
   padding-right: 15px;
   padding-top: 1px;
   padding-bottom: 1px;
  }
</style>
</head>
<body>
<address style="text-align: left;">
Document number: N4387<br/>
Date: 2015-03-14<br/>
Revises: N4064<br/>
Authors: Daniel Kr&uuml;gler, Geoffrey Romer, Ville Voutilainen<br/>
Project: Programming Language C++, Library Working Group<br/>
Reply-to: <a href="mailto:daniel.kruegler@gmail.com">Daniel Kr&uuml;gler</a>
</address>
<hr>
<h1 style="text-align: center;">Improving <tt>pair</tt> and <tt>tuple</tt>, revision 3</h1>
<p>
<strong>Addressed issues</strong>: 
</p>
<ul>
<li><p>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2051">LWG 2051</a>.
</p></li>
<li><p>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2397">LWG 2397</a>.
</p></li>
<li><p>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2312">LWG 2312</a> is <em>partially</em> addressed: The currently 
proposed wording still intends to make an implementation conforming that would accept a smaller number of elements values compared to the
actual tuple-size (and to value-initialize the remaining ones), therefore the size-related requirements are currently not part of the
SFINAE constraints. If LWG 2312 would be accepted the corresponding constraints would be similarly adjusted as described by the issue 
and the corresponding requirement could be removed.
</p></li>
</ul>
<p>
<h2><a name="RevisionHistory"></a>Revision History</h2>
<p>
Changes since <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4064.html">N4064</a> (revision 2):
</p>
<ul>
<li><p>
Improve and simplify definition of <tt><i>EXPLICIT</i></tt> as well as the individual member specifications by separating out 
the number of constructor declarations from the decision to add <tt>explicit</tt> or not.
</li></p>
<li><p>
After the Cologne meeting the authors recognized that three of the existing <tt>tuple</tt> allocator constructors haven been
incorrectly marked with <tt><i>EXPLICIT</i></tt>. The constructors
</p>
<blockquote><pre>
template &lt;class Alloc&gt;
  tuple(allocator_arg_t, const Alloc&amp; a);
template &lt;class Alloc&gt;
  tuple(allocator_arg_t, const Alloc&amp; a, const tuple&amp;);
template &lt;class Alloc&gt;
  tuple(allocator_arg_t, const Alloc&amp; a, tuple&amp;&amp;);
</pre></blockquote>
<p>
correspond to the three non-allocator constructors
</p>
<blockquote><pre>
constexpr tuple();
tuple(const tuple&amp;) = default;
tuple(tuple&amp;&amp;) = default;
</pre></blockquote>
<p>
and none of these can be <tt>explicit</tt> as declared (The core language does not propagate <tt>explicit</tt> for
special members when declared in that form). The whole idea of propagating <tt><i>EXPLICIT</i></tt> to the
allocator constructors was to reflect the <tt>explicit</tt>-nature of the <em>corresponding</em> non-tuple constructors. To
realize this, <tt><i>EXPLICIT</i></tt> need to be removed from the three aforementioned constructors.
</p>
</li>
</ul>
<p>
Changes since <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3739.html">N3739</a> (revision 1):
</p>
<ul>
<li><p>Improved the current rationale (Thanks to Mike Spertus!)</p>
</li>
<li><p>During the Rapperswil LEWG discussion a new vote lead to a revised result on the preferred
representation form:</p>
<blockquote>
<p>
Do we prefer the <tt><i>EXPLICIT(see below)</i> constexpr tuple(UTypes&amp;&amp;...);</tt> editorial representation?
<p/>
SF-F-N-A-SA
<p/>
0-8-3-2-0
</p>
</blockquote>
<p>Therefore this revision now uses the annotation <tt><i>EXPLICIT</i></tt> for the affected constructor pairs
and defines the meaning of that in Clause 17.</p>
</li>
</ul>

<p>
Changes since <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3680.html">N3680</a>:
</p>
<ul>
<li><p>
During a straw-pool vote there was a small majority (4:3) in favour for keeping the two-signatures approach,
so this presentation form was used in this revision.
</p></li>
<li><p>
The original example has been improved.
</p></li>
<li><p>
The missing application of the declaration pattern to the <tt>allocator_arg_t</tt> constructors has been fixed.
</p></li>
<li><p>
Consequent usage of the more precise <tt>is_convertible</tt> trait instead of the somewhat vague 
<em>is implicitly convertible</em> description.
</p></li>
</ul>
<h2><a name="Introduction"></a>Introduction</h2>
<p>
For many programmers it is a surprise to find out, that the following code is rejected by their compiler:
</p>
<blockquote><pre>
std::tuple&lt;int, int&gt; pixel_coordinates() 
{
  return {10, -15};  <span style="color:#C80000;font-weight:bold">// Oops: Error</span>
}

struct NonCopyable { NonCopyable(int); NonCopyable(const NonCopyable&amp;) = delete; };

std::pair&lt;NonCopyable, double&gt; pmd{42, 3.14};  <span style="color:#C80000;font-weight:bold">// Oops: Error</span>
</pre></blockquote>

<p>
<strong>What is wrong with this? Why doesn't this just work?</strong>
<p/>
This paper explains the reason for the current specification of <tt>pair</tt> and <tt>tuple</tt> and suggests
changes to the working paper to fix these and some other bothersome constraints of these general type wrappers.
</p>

<h2><a name="History"></a>Looking backwards</h2>
<p>
At the time when <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3140.html">N3240</a> was
proposed, several driving forces defined the constraints of resolving a bunch of library issues and NB 
comments.
<p/>
One notable intention was to prevent that the type wrappers <tt>tuple</tt> and <tt>pair</tt> should allow
implicit conversions for wrapped types that are not implicitly convertible, as expressed by 
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#1324">LWG 1324</a> and
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3118.html#DE15">DE 15</a>.
<p/>
Another relevant requirement was to keep backward-compatibility to C++03 in regard to null pointer literals
expressed as integral null constants as described by
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#811">LWG 811</a>.
<p/>
At that time there was a strong resistance to add further constructors especially to <tt>std::pair</tt>. At some point in
time there did exist a very large number of such constructors due to allocator support. One important consequence 
of this pair simplification was the acceptance of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3059.pdf">N3059</a>.
<p/>
Thus with the previous acceptance of proposal <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3140.html">N3240</a>
the specification provides the following <strong>advantages</strong> for <tt>pair</tt> and <tt>tuple</tt>:
<p>
<ol>
<li><p>
Heterogenous template constructors are constrained upon the criterion that the element-wise source types are 
<em>implicitly convertible</em> to the element-wise destination types.
</p>
<blockquote><pre>
struct B { explicit B(bool); };

std::tuple&lt;B&gt; tb = std::tuple&lt;bool&gt;(); <span style="color:#006600;font-weight:bold">// Error</span>
</pre></blockquote>
</li>
<li><p>
The non-template constructor <tt>tuple(const Types&amp;...)</tt> and the corresponding template-constructor are 
<em>explicit</em>. This prevents that a single-element tuple from being <strong>copy-initialized</strong> by an 
argument object and has only an <em>explicit</em> constructor for this construction.
</p>
<blockquote><pre>
struct X { X(); explicit X(const X&amp;); } x;

std::tuple&lt;X&gt; tx = x; <span style="color:#006600;font-weight:bold">// Error</span>

struct E { explicit E(int); };

std::tuple&lt;E&gt; te = 42; <span style="color:#006600;font-weight:bold">// Error</span>
</pre></blockquote>
</li>
<li><p>
Non-template constructors accepting a sequence of elements, such as <tt>explicit tuple(const Types&amp;...)</tt>
and <tt>pair(const T1&amp; x, const T2&amp; y)</tt>, are still kept to support the special conversion scenario where a 
pointer(-to-member) element type is initialized with the <strong>null pointer constant <tt>0</tt></strong> instead of <tt>nullptr</tt>.
</p>
<blockquote><pre>
class C;

std::tuple&lt;int*&gt; tpi(0); <span style="color:#006600;font-weight:bold">// OK</span>
std::tuple&lt;int C::*&gt; tpmi(0); <span style="color:#006600;font-weight:bold">// OK</span>
</pre></blockquote>
</li>
</ol>

<h2><a name="Discussion"></a>Discussion</h2>
<p>
We propose that <tt>pair</tt>/<tt>tuple</tt> obey the same initialization rules as their underlying element types. Unless we have 
such "perfect initialization", <tt>pair</tt> and <tt>tuple</tt> exhibit confusing and unintuitive behavior as illustrated 
by the examples below.
</p>
<ol>
<li>
<p/>
It means that <tt>tuple</tt> objects cannot be <em>returned</em> from a function as simple as this:
</p>
<blockquote><pre>
std::tuple&lt;int, int&gt; foo_tuple() 
{
  return {1, -1};  <span style="color:#C80000;font-weight:bold">// Error</span>
}

std::pair&lt;int, int&gt; foo_pair() 
{
  return {1, -1};  <span style="color:#006600;font-weight:bold">// OK</span>
}
</pre></blockquote>
</li>

<li>
<p/>
It means that <tt>tuple</tt> or <tt>pair</tt> objects cannot be <em>constructed</em> for element types that cannot be copied:
</p>
<blockquote><pre>
struct D { D(int); D(const D&amp;) = delete; };

std::tuple&lt;D&gt; td(12); <span style="color:#C80000;font-weight:bold">// Error</span>
</pre></blockquote>
</li>

<li>
<p/>
It even means that <tt>tuple</tt> or <tt>pair</tt> objects cannot be <em>direct-constructed</em> for element types via an explicit 
conversion:
</p>
<blockquote><pre>
struct Y { explicit Y(int); };

std::tuple&lt;Y&gt; ty(12); <span style="color:#C80000;font-weight:bold">// Error</span>
</pre></blockquote>
</li>

<li>
<p>
It has been observed by <a href="http://stackoverflow.com/questions/11386042/confused-by-default-constructor-description-of-stdtuple-in-the-iso-c-standar">Johannes Schaub</a> 
that there exists a defect with <tt>tuple</tt> in regard to the 
non-template constructor <tt>explicit tuple(const Types&amp;...)</tt>: The current specification has the effect that
the instantiation of <tt>tuple&lt;&gt;</tt> would be required to be ill-formed because it has two conflicting default 
constructors.
</p>
</li>
</ol>

<p>Starting with the last point: This is indeed a simple oversight that slipped in during the <tt>tuple</tt> standardization. 
The <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf">TR1</a> document did have the following specification:</p>
<blockquote><pre>
template &lt;class T1 = <em>unspecified</em> ,
          class T2 = <em>unspecified</em> ,
          ...,
          class TM = <em>unspecified</em> &gt;
class tuple
{
public:
  tuple();
  explicit tuple(P1, P2, ..., PN); <em><span style="color:black;font-weight:bold">// iff N &gt; 0</span></em>
  [&hellip;]
};
</pre></blockquote>

<p>When the variadic form of tuples was proposed via <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2151.pdf">N2151</a>
and its successors, the highlighted size constraint inadvertently got lost.</p>

<p>The other three problems are all caused by (A) constructors that are always <em>explicit</em> and (B) by constrained constructor
templates that impose <em>implicit convertible</em> constraints on the element types.</p>

<p>So, notwithstanding the good motivation behind the current specification of <tt>pair</tt> and <tt>tuple</tt>, it turns out to have
some unfortunate consequences. 
</p>

<p>This proposal is intending to solve all these problems by a simple procedure that still ensures that all positive aspects of the current
specification are conserved.</p>

<h2><a name="perfect_init"></a>"Perfect initialization"</h2>
<p>
Before explaining the general outline of this proposal it is more helpful to start with a simple, but useful programming idiom. 
<p/>
Consider the following class template <tt>A</tt> that is intended to be used as a wrapper for some other type <tt>T</tt>:
</p>
<blockquote><pre>
#include &lt;type_traits&gt;
#include &lt;utility&gt;

template&lt;class T&gt;
struct A {
  template&lt;class U,
    typename std::enable_if&lt;
      <span style="color:#3399FF;font-weight:bold">std::is_constructible&lt;T, U&gt;::value &amp;&amp;</span>
      <span style="color:#3399FF;font-weight:bold">std::is_convertible&lt;U, T&gt;::value</span>
    , bool&gt;::type = false
  &gt;
  A(U&amp;&amp; u) : t(std::forward&lt;U&gt;(u)) {}

 template&lt;class U,
    typename std::enable_if&lt;
      <span style="color:#3399FF;font-weight:bold">std::is_constructible&lt;T, U&gt;::value &amp;&amp;</span>
      <span style="color:#3399FF;font-weight:bold">!std::is_convertible&lt;U, T&gt;::value</span>
    , bool&gt;::type = false
  &gt;
  explicit A(U&amp;&amp; u) : t(std::forward&lt;U&gt;(u)) {}
  
  T t;
};
</pre></blockquote>

<p>
The shown constructors both use <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2027.html">perfect forwarding</a>
and they have essentially the same signatures except for one being explicit, the other one not. Furthermore, they are
<em>mutually exclusively</em> constrained. In other words: This combination behaves for any destination type <tt>T</tt> and any 
argument type <tt>U</tt> like a <em>single</em> constructor that is <strong>either explicit or non-explicit</strong> (or no constructor
at all). Attempts to construct a <tt>A&lt;T&gt;</tt> from some value of type <tt>U</tt> will reflect the allowed initialization forms 
of the wrapped type <tt>T</tt>:
</p>

<blockquote><pre>
struct Im{ Im(int){} };
struct Ex{ explicit Ex(int){} };

A&lt;Im&gt; ai1(1); // OK
A&lt;Im&gt; ai2{2}; // OK

A&lt;Im&gt; ai3 = 3;   // OK
A&lt;Im&gt; ai4 = {4}; // OK

A&lt;Ex&gt; ae1(1); // OK
A&lt;Ex&gt; ae2{2}; // OK

A&lt;Ex&gt; ae3 = 3;   // Error
A&lt;Ex&gt; ae4 = {4}; // Error
</pre></blockquote>

<p>
This technique can easily be extended to the variadic template case, and when doing so can be considered as a key to solving
the problems of <tt>tuple</tt> and <tt>pair</tt>.

<p/>
It should be noted here, that for the general case the <tt>std::is_constructible&lt;T, U&gt;::value</tt> requirement for the
non-explicit constructor which is constrained on <tt>std::is_convertible&lt;U, T&gt;::value</tt> is not redundant, because it
is possible to create types that can be copy-initialized but not direct-initialized:
</p>
<blockquote><pre>
struct Odd {
  explicit Odd(int) = delete;
  Odd(long){}
};

Odd o2 = 1; // OK
Odd o1(1);  // Error
</pre></blockquote>

<p>
Technically it would be possible to apply the same technique of creating element-dependent explicit or non-explicit default
constructors. This application was shortly considered during the write-up of this proposal, but rejected because for the 
current C++ rules there is no longer any observable difference for an <tt>explicit</tt>  default constructor that cannot be 
invoked with more than zero arguments and one that is not <tt>explicit</tt>.
<p/>
The technique cannot be applied to copy/move operators in the same way as for the other constructors (because these special
member functions cannot be templates) and given the very rare request for such a support the idea was no further investigated 
by the author. A second argument against providing this support is based on the consistency with the core language rules
that the <tt>explicit</tt>-character of these constructors is not conserved for the implicitly declared versions in classes 
that contain corresponding sub-objects with such explicit constructors. 
</p>

<h2><a name="Outline"></a>Outline</h2>

<p>
As shown above, the current over-constraining restrictions of the <tt>pair</tt> and <tt>tuple</tt> constructors are due to
unconditional usage of <em>explicit</em> and <em>implicitly convertible</em> requirements.
<p/>
The general approach of this proposal is to require "perfect initialization" semantics for <tt>pair</tt> and <tt>tuple</tt> 
constructors extended to the variadic case. Albeit this seemingly doubles the number of constructor declarations in the draft, 
it does not change the <em>effective</em> number of these for a particular combination of element type and source type of 
some initialization due to their mutual exclusion property. 
<p/>
In theory the same technique could be applied to the <tt>piecewise_construct_t</tt> of <tt>pair</tt>. This proposal does 
not propose this, because this constructor is specifically asked for by the corresponding tag and there are no further
constraint except the <tt>is_constructible</tt> requirements.
<p/>
In addition, this proposal fixes the specification problem of <tt>tuple&lt;&gt;</tt>'s default constructors.
<p/>
The wording is intentionally chosen, so that an implementation is not required (but allowed) to use the "perfect initialization" idiom.
<p/>
This is done by taking advantage of the already existing nomenclature "This function does not participate in overload resolution 
unless [&hellip;]". Its worth emphasizing that even though this phrase is usually used to describe constrained templates 
in the Library specification, the actual wording of this doesn't necessarily imply to "sfinae out" template functions. Many library 
implementations solve this problem by providing a specialization for the empty <tt>tuple</tt> case that does not provide 
the additional default constructor, for example. This is also a valid way to ensure that functions don't participate in overload resolution.
</p>

<h2><a name="WhyNotExplicitSingleArgs"></a>Why not explicit for single argument constructors only?</h2>
<p>
In C++03 <tt>explicit</tt> constructors had no behavioural difference, unless they had been single-argument constructors, so
one might suggest to restrict adding the <tt>explicit</tt> keyword to constructors that take exactly one argument.
<p/>
I think this is idea is flawed (unless I'm using specifically tagged constructors like the piecewise-one of <tt>pair</tt>). Consider 
the following example:
</p>
<blockquote><pre>
#include &lt;tuple&gt;
#include &lt;chrono&gt;
#include &lt;iostream&gt;

using hms_t = std::tuple&lt;std::chrono::hours, std::chrono::minutes, std::chrono::seconds&gt;;

void launch_rocket_at(std::chrono::seconds s)
{
  std::cout &lt;&lt; "launching rocket in " &lt;&lt; s.count() &lt;&lt; " seconds!\n";
}

void launch_rocket_at(hms_t times)
{
  using namespace std;
  launch_rocket_at(get&lt;0&gt;(times) + get&lt;1&gt;(times) + get&lt;2&gt;(times));
}

int main()
{
  using namespace std;
  <span style="color:#C80000;font-weight:bold">launch_rocket_at(make_tuple(1, 2, 3)); // #1: very scary</span>
  <span style="color:#C80000;font-weight:bold">launch_rocket_at({1, 2, 3});           // #2: even scarier</span>
  using namespace std::chrono;
  <span style="color:#006600;font-weight:bold">launch_rocket_at(make_tuple(hours(1), minutes(2), seconds(3))); // #3: Perfectly clear!</span>
  <span style="color:#006600;font-weight:bold">launch_rocket_at({hours(1), minutes(2), seconds(3)});           // #4: Also clear!</span>
  <span style="color:#006600;font-weight:bold">launch_rocket_at(hms_t{1, 2, 3});                               // #5: And this, too</span>
}
</pre></blockquote>

<p>
which should output:
</p>

<blockquote><pre>
launching rocket in 3723 seconds!
launching rocket in 3723 seconds!
launching rocket in 3723 seconds!
</pre></blockquote>

<p>
If the former two calls to function <tt>launch_rocket_at</tt> where possible, this would directly subvert the
intended explicitness of the <tt>std::duration</tt> constructor and would make using the time-utility
types much more unsafe. Why? Consider the following scenario:
<p/>
If the client believed that the order of the units was <em>seconds, minutes, hours</em>, and input 3, 2, 1, &mdash; 
intending 3 seconds, 2 minutes, and 1 hour &mdash; the rocket would launch in 10,921 seconds instead of the intended 
3,723 seconds. This mistake can indeed easily happen, if you look again at the lines marked with <b>#1</b> and  <b>#2</b>.
<p/>
Due to our intentionally conserved constraints to be explicit here we catch that mistake at compile-time, 
instead of having to shoot the rocket down...
</p>

<h2><a name="WordingForm"></a>Editorial Representation</h2>
<p>
During the write-up of this proposal I had the idea of replacing the prototype declaration pairs by
a single one expressed by some pseudo-macro that looks like a single declaration. For example
</p>
<blockquote><pre>
template &lt;class... UTypes&gt;
constexpr tuple(UTypes&amp;&amp;...);
template &lt;class... UTypes&gt;
explicit constexpr tuple(UTypes&amp;&amp;...);
</pre></blockquote>

<p>could instead be declared as follows:</p>

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

<p>This form of representation still means that <tt><i>EXPLICIT</i></tt> needs to be defined somewhere
and somehow, but only once. 
<p/>
There was a strong preference during the Rapperswil 2014 LEWG discussion to use the 
"macro" instead of the individual declarations.
<p/>
This paper does not use a previously suggested form of <tt><i>EXPLICIT(see below)</i></tt> instead of <tt><i>EXPLICIT</i></tt>, 
because there is nothing specific to explain below again (The different SFINAE conditions are not relevant at that point,
because they appear as usual with the normal, detailed prototype specifications).
<p/>
In any way, the final editorial decision is being handed over to the project editor.
</p>

<h2><a name="Proposed_resolution"></a>Proposed resolution</h2>
<p>
The proposed wording changes refer to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf">N4296</a>.
</p>
<ol>
<li><p>Add an additional new paragraph at the end of 17.5.2.2 [functions.within.classes] and move the current second paragraph to the end of the first
paragraph:</p>

<blockquote>
<p>
-1- For the sake of exposition, Clauses 18 through 30 and Annex D do not describe copy/move constructors,
assignment operators, or (non-virtual) destructors with the same apparent semantics as those that can be
generated by default (12.1, 12.4, 12.8). <ins>It is unspecified whether the implementation provides explicit 
definitions for such member function signatures, or for virtual destructors that can be generated by default.</ins>
<p/>
<del>-2- It is unspecified whether the implementation provides explicit definitions for such member function signatures,
or for virtual destructors that can be generated by default.</del>
</p>
<p><ins>-?- For the sake of exposition, the library clauses sometimes annotate constructors with <tt><i>EXPLICIT</i></tt>. Such a 
constructor is conditionally declared as either explicit or non-explicit (12.3.1 [class.conv.ctor]). [<i>Note</i>: This is typically 
implemented by declaring two such constructors, of which at most one participates in overload resolution &mdash; <i>end note</i>]</ins>
</p>

</blockquote>
</li>

<li>
<p>Change 20.3.2 [pairs.pair], class template <tt>pair</tt> synopsis, as indicated:</p>
<blockquote>
<pre>
namespace std {
  template &lt;class T1, class T2&gt;
  struct pair {
    typedef T1 first_type;
    typedef T2 second_type;

    T1 first;
    T2 second;
    pair(const pair&amp;) = default;
    pair(pair&amp;&amp;) = default;
    constexpr pair();
    <ins><i>EXPLICIT</i></ins> constexpr pair(const T1&amp; x, const T2&amp; y);
    template&lt;class U, class V&gt; <ins><i>EXPLICIT</i></ins> constexpr pair(U&amp;&amp; x, V&amp;&amp; y);
    template&lt;class U, class V&gt; <ins><i>EXPLICIT</i></ins> constexpr pair(const pair&lt;U, V&gt;&amp; p);
    template&lt;class U, class V&gt; <ins><i>EXPLICIT</i></ins> constexpr pair(pair&lt;U, V&gt;&amp;&amp; p);
    template &lt;class... Args1, class... Args2&gt;
    pair(piecewise_construct_t,
      tuple&lt;Args1...&gt; first_args, tuple&lt;Args2...&gt; second_args);

    pair&amp; operator=(const pair&amp; p);
    template&lt;class U, class V&gt; pair&amp; operator=(const pair&lt;U, V&gt;&amp; p);
    pair&amp; operator=(pair&amp;&amp; p) noexcept(<em>see below</em>);
    template&lt;class U, class V&gt; pair&amp; operator=(pair&lt;U, V&gt;&amp;&amp; p);

    void swap(pair&amp; p) noexcept(<em>see below</em>);
  };
}
</pre>
</blockquote>
</li>
<li><p>Change 20.3.2 [pairs.pair] around p5 as indicated:</p>
<blockquote><pre>
<ins><i>EXPLICIT</i></ins> constexpr pair(const T1&amp; x, const T2&amp; y);
</pre><blockquote>
<p>
<del>-5- <em>Requires</em>: <tt>is_copy_constructible&lt;first_type&gt;::value</tt> is <tt>true</tt> and 
<tt>is_copy_constructible&lt;second_type&gt;::value</tt> is <tt>true</tt>.</del>
<p/>
-6- <em>Effects</em>: The constructor initializes <tt>first</tt> with <tt>x</tt> and <tt>second</tt> with <tt>y</tt>.
<p/>
<ins>-?- <em>Remarks</em>: This constructor shall not participate in overload resolution unless
<tt>is_copy_constructible&lt;first_type&gt;::value</tt> is <tt>true</tt> and 
<tt>is_copy_constructible&lt;second_type&gt;::value</tt> is <tt>true</tt>. The constructor is explicit if and only if 
<tt>is_convertible&lt;const first_type&amp;, first_type&gt;::value</tt> is <tt>false</tt> or 
<tt>is_convertible&lt;const second_type&amp;, second_type&gt;::value</tt> is <tt>false</tt>.</ins>
</p>
</blockquote></blockquote>
</li>

<li><p>Change 20.3.2 [pairs.pair] around p7 as indicated:</p>
<blockquote><pre>
template&lt;class U, class V&gt; <ins><i>EXPLICIT</i></ins> constexpr pair(U&amp;&amp; x, V&amp;&amp; y);
</pre><blockquote><p>
<del>-7- <em>Requires</em>: <tt>is_constructible&lt;first_type, U&amp;&amp;&gt;::value</tt> is <tt>true</tt> and 
<tt>is_constructible&lt;second_type, V&amp;&amp;&gt;::value</tt> is <tt>true</tt>.</del>
<p/>
-8- <em>Effects</em>: The constructor initializes <tt>first</tt> with <tt>std::forward&lt;U&gt;(x)</tt> and <tt>second</tt> with 
<tt>std::forward&lt;V&gt;(y)</tt>.
<p/>
-9- <em>Remarks</em>: <del>If <tt>U</tt> is not implicitly convertible to <tt>first_type</tt> or <tt>V</tt> is not implicitly convertible to 
  <tt>second_type</tt> this constructor shall not participate in overload resolution.</del>
  <ins>This constructor shall not participate in overload resolution unless <tt>is_constructible&lt;first_type, U&amp;&amp;&gt;::value</tt> 
  is <tt>true</tt> and <tt>is_constructible&lt;second_type, V&amp;&amp;&gt;::value</tt> is <tt>true</tt>. The constructor is explicit 
  if and only if <tt>is_convertible&lt;U&amp;&amp;, first_type&gt;::value</tt> is <tt>false</tt> or <tt>is_convertible&lt;V&amp;&amp;, second_type&gt;::value</tt> 
  is <tt>false</tt>.</ins>
 </p>
</blockquote></blockquote>
</li>

<li><p>Change 20.3.2 [pairs.pair] around p10 as indicated:</p>
<blockquote><pre>
template&lt;class U, class V&gt; <ins><i>EXPLICIT</i></ins> constexpr pair(const pair&lt;U, V&gt;&amp; p);
</pre><blockquote><p>
<del>-10- <em>Requires</em>: <tt>is_constructible&lt;first_type, const U&amp;&gt;::value</tt> is <tt>true</tt> and 
	<tt>is_constructible&lt;second_type, const V&amp;&gt;::value</tt> is <tt>true</tt>.</del>
<p/>
-11- <em>Effects</em>: <ins>The constructor initializes</ins><del>Initializes</del> members from the corresponding members of the argument.
<p/>
-12- <em>Remark<ins>s</ins></em>: This constructor shall not participate in overload resolution unless <del><tt>const U&amp;</tt> is 
    implicitly convertible to <tt>first_type</tt> and <tt>const V&amp;</tt> is implicitly convertible to <tt>second_type</tt></del>
    <ins><tt>is_constructible&lt;first_type, const U&amp;&gt;::value</tt> is <tt>true</tt> and 
	<tt>is_constructible&lt;second_type, const V&amp;&gt;::value</tt> is <tt>true</tt>. The constructor is explicit 
    if and only if <tt>is_convertible&lt;const U&amp;, first_type&gt;::value</tt> is <tt>false</tt> or 
	<tt>is_convertible&lt;const V&amp;, second_type&gt;::value</tt> is <tt>false</tt></ins>.
</p>
</blockquote></blockquote>
</li>
<li><p>Change 20.3.2 [pairs.pair] around p13 as indicated:</p>
<blockquote><pre>
template&lt;class U, class V&gt; <ins><i>EXPLICIT</i></ins> constexpr pair(pair&lt;U, V&gt;&amp;&amp; p);
</pre><blockquote><p>
<del>-13- <em>Requires</em>: <tt>is_constructible&lt;first_type, U&amp;&amp;&gt;::value</tt> is <tt>true</tt> and 
	<tt>is_constructible&lt;second_type, V&amp;&amp;&gt;::value</tt> is <tt>true</tt>.</del>
<p/>
-14- <em>Effects</em>: The constructor initializes <tt>first</tt> with <tt>std::forward&lt;U&gt;(p.first)</tt> 
and <tt>second</tt> with <tt>std::forward&lt;V&gt;(p.second)</tt>.
<p/>
-15- <em>Remark<ins>s</ins></em>: This constructor shall not participate in overload resolution unless <del><tt>U</tt> is 
implicitly convertible to <tt>first_type</tt> and <tt>V</tt> is implicitly convertible to <tt>second_type</tt></del>
<ins><tt>is_constructible&lt;first_type, U&amp;&amp;&gt;::value</tt> is <tt>true</tt> and 
<tt>is_constructible&lt;second_type, V&amp;&amp;&gt;::value</tt> is <tt>true</tt>. The constructor is explicit 
if and only if <tt>is_convertible&lt;U&amp;&amp;, first_type&gt;::value</tt> is <tt>false</tt> or 
<tt>is_convertible&lt;V&amp;&amp;, second_type&gt;::value</tt> is <tt>false</tt></ins>.
</p>
</blockquote></blockquote>
</li>

<li><p>Change 20.4.2 [tuple.tuple], class template <tt>tuple</tt> synopsis, as indicated. The intent is to declare
the set of <em>"conditionally explicit"</em> constructors and to fix the <em>multiple default constructor</em>
problem for empty tuples.</p>
<blockquote><pre>
namespace std {
  template &lt;class... Types&gt;
  class tuple {
  public:
    // 20.4.2.1, tuple <em>construction</em>
    constexpr tuple();
    <ins><i>EXPLICIT</i></ins> constexpr <del>explicit</del> tuple(const Types&amp;...); <ins><em>// only if</em> sizeof...(Types) &gt;= 1</ins>
    template &lt;class... UTypes&gt;
      <ins><i>EXPLICIT</i></ins> constexpr <del>explicit</del> tuple(UTypes&amp;&amp;...);   <ins><em>// only if</em> sizeof...(Types) &gt;= 1</ins>
    
    tuple(const tuple&amp;) = default;
    tuple(tuple&amp;&amp;) = default;
  
    template &lt;class... UTypes&gt;
      <ins><i>EXPLICIT</i></ins> constexpr tuple(const tuple&lt;UTypes...&gt;&amp;);
    template &lt;class... UTypes&gt;
      <ins><i>EXPLICIT</i></ins> constexpr tuple(tuple&lt;UTypes...&gt;&amp;&amp;);

    template &lt;class U1, class U2&gt;
      <ins><i>EXPLICIT</i></ins> constexpr tuple(const pair&lt;U1, U2&gt;&amp;);          <em>// only if</em> sizeof...(Types) == 2
    template &lt;class U1, class U2&gt;
      <ins><i>EXPLICIT</i></ins> constexpr tuple(pair&lt;U1, U2&gt;&amp;&amp;);               <em>// only if</em> sizeof...(Types) == 2

    <em>// allocator-extended constructors</em>
    template &lt;class Alloc&gt;
      tuple(allocator_arg_t, const Alloc&amp; a);
    template &lt;class Alloc&gt;
      <ins><i>EXPLICIT</i></ins> tuple(allocator_arg_t, const Alloc&amp; a, const Types&amp;...);
    template &lt;class Alloc, class... UTypes&gt;
      <ins><i>EXPLICIT</i></ins> tuple(allocator_arg_t, const Alloc&amp; a, UTypes&amp;&amp;...);
    template &lt;class Alloc&gt;
      tuple(allocator_arg_t, const Alloc&amp; a, const tuple&amp;);
    template &lt;class Alloc&gt;
      tuple(allocator_arg_t, const Alloc&amp; a, tuple&amp;&amp;);
    template &lt;class Alloc, class... UTypes&gt;
      <ins><i>EXPLICIT</i></ins> tuple(allocator_arg_t, const Alloc&amp; a, const tuple&lt;UTypes...&gt;&amp;);
    template &lt;class Alloc, class... UTypes&gt;
      <ins><i>EXPLICIT</i></ins> tuple(allocator_arg_t, const Alloc&amp; a, tuple&lt;UTypes...&gt;&amp;&amp;);
    template &lt;class Alloc, class U1, class U2&gt;
      <ins><i>EXPLICIT</i></ins> tuple(allocator_arg_t, const Alloc&amp; a, const pair&lt;U1, U2&gt;&amp;);
    template &lt;class Alloc, class U1, class U2&gt;
      <ins><i>EXPLICIT</i></ins> tuple(allocator_arg_t, const Alloc&amp; a, pair&lt;U1, U2&gt;&amp;&amp;);

    [..]
  };
}
</pre></blockquote>
</li>
<li><p>Change 20.4.2.1 [tuple.cnstr] around p6 as indicated:</p>
<blockquote><pre>
<ins><i>EXPLICIT</i></ins> constexpr <del>explicit</del> tuple(const Types&amp;...);
</pre><blockquote><p>
<del>-6- <em>Requires</em>: <tt>is_copy_constructible&lt;Ti&gt;::value</tt> is true for all <em>i</em>.</del>
<p/>
-7- <em>Effects</em>: <ins>The constructor initializes</ins><del>Initializes</del> each element with the value of the corresponding parameter.
<p/>
<ins>-?- <em>Remarks</em>: This constructor shall not participate in overload resolution unless <tt>sizeof...(Types) &gt;= 1</tt> and
<tt>is_copy_constructible&lt;<em>T<sub>i</sub></em>&gt;::value</tt> is <tt>true</tt> for all <em>i</em>. The constructor is explicit 
if and only if <tt>is_convertible&lt;const <em>T<sub>i</sub></em>&amp;, <em>T<sub>i</sub></em>&gt;::value</tt> is <tt>false</tt> for at least one <em>i</em>.</ins>
</p>
</blockquote></blockquote>
<p>
</li>
<li><p>Change 20.4.2.1 [tuple.cnstr] around p8 as indicated:</p>
<blockquote><pre>
template &lt;class... UTypes&gt;
  <ins><i>EXPLICIT</i></ins> constexpr <del>explicit</del> tuple(UTypes&amp;&amp;... u);
</pre><blockquote><p>
-8- <em>Requires</em>: <tt>sizeof...(Types) == sizeof...(UTypes)</tt>. <del><tt>is_constructible&lt;<em>T<sub>i</sub></em>, 
<em>U<sub>i</sub></em>&amp;&amp;&gt;::value</tt> is true for all <em>i</em>.</del>
<p/>
-9- <em>Effects</em>: <ins>The constructor initializes</ins><del>Initializes</del> the elements in the tuple with the corresponding value in <tt>std::forward&lt;UTypes&gt;(u)</tt>.
<p/>
-10- <em>Remark<ins>s</ins></em>: This constructor shall not participate in overload resolution unless <del>each type in <tt>UTypes</tt> is implicitly convertible 
	to its corresponding type in <tt>Types</tt></del>
	<ins><tt>sizeof...(Types) &gt;= 1</tt> and <tt>is_constructible&lt;<em>T<sub>i</sub></em>, <em>U<sub>i</sub></em>&amp;&amp;&gt;::value</tt> is <tt>true</tt> for all <em>i</em>. 
	The constructor is explicit if and only if <tt>is_convertible&lt;<em>U<sub>i</sub></em>&amp;&amp;, <em>T<sub>i</sub></em>&gt;::value</tt> is <tt>false</tt> for 
	at least one <em>i</em></ins>.
</p>
</blockquote></blockquote>
</li>
<li><p>Change 20.4.2.1 [tuple.cnstr] around p15 as indicated:</p>
<blockquote><pre>
template &lt;class... UTypes&gt; <ins><i>EXPLICIT</i></ins> constexpr tuple(const tuple&lt;UTypes...&gt;&amp; u);
</pre><blockquote><p>
-15- <em>Requires</em>: <tt>sizeof...(Types) == sizeof...(UTypes)</tt>. <del><tt>is_constructible&lt;<em>T<sub>i</sub></em>, const <em>U<sub>i</sub></em>&amp;&gt;::value</tt> 
	 is true for all <em>i</em>.</del>
<p/>
-16- <em>Effects</em>: <ins>The constructor initializes</ins><del>Constructs</del> each element of <tt>*this</tt> with the corresponding element of <tt>u</tt>.
<p/>
-17- <em>Remark<ins>s</ins></em>: This constructor shall not participate in overload resolution unless 
	<del><tt>const <em>U<sub>i</sub></em>&amp;</tt> is implicitly convertible to <tt><em>T<sub>i</sub></em></tt> for all <em>i</em></del>
	<ins><tt>is_constructible&lt;<em>T<sub>i</sub></em>, const <em>U<sub>i</sub></em>&amp;&gt;::value</tt> is <tt>true</tt> for all <em>i</em>. 
	The constructor is explicit if and only if <tt>is_convertible&lt;const <em>U<sub>i</sub></em>&amp;, <em>T<sub>i</sub></em>&gt;::value</tt> 
	is <tt>false</tt> for at least one <em>i</em></ins>.
</p>
</blockquote></blockquote>
</li>
<li><p>Change 20.4.2.1 [tuple.cnstr] around p18 as indicated:</p>
<blockquote><pre>
template &lt;class... UTypes&gt; <ins><i>EXPLICIT</i></ins> constexpr tuple(tuple&lt;UTypes...&gt;&amp;&amp; u);
</pre><blockquote><p>
-18- <em>Requires</em>: <tt>sizeof...(Types) == sizeof...(UTypes)</tt>. <del><tt>is_constructible&lt;<em>T<sub>i</sub></em>, 
<em>U<sub>i</sub></em>&amp;&amp;&gt;::value</tt> is true for all <em>i</em>.</del>
<p/>
-19- <em>Effects</em>: For all <em>i</em>, <ins>the constructor</ins> initializes the <em>i</em><sup>th</sup> element of 
<tt>*this</tt> with <tt>std::forward&lt;<em>U<sub>i</sub></em>&gt;(get&lt;<em>i</em>&gt;(u))</tt>.
<p/>
-20- <em>Remark<ins>s</ins></em>: This constructor shall not participate in overload resolution unless <del>each type in <tt>UTypes</tt> 
is implicitly convertible to its corresponding type in <tt>Types</tt></del>
	<ins><tt>is_constructible&lt;<em>T<sub>i</sub></em>, <em>U<sub>i</sub></em>&amp;&amp;&gt;::value</tt> is <tt>true</tt> for all <em>i</em>. 
	The constructor is explicit if and only if <tt>is_convertible&lt;<em>U<sub>i</sub></em>&amp;&amp;, <em>T<sub>i</sub></em>&gt;::value</tt> 
	is <tt>false</tt> for at least one <em>i</em></ins>.
</p>
</blockquote></blockquote>
</li>
<li>
<p>Change 20.4.2.1 [tuple.cnstr] around p21 as indicated:</p>
<blockquote><pre>
template &lt;class U1, class U2&gt; <ins><i>EXPLICIT</i></ins> constexpr tuple(const pair&lt;U1, U2&gt;&amp; u);
</pre><blockquote><p>
-21- <em>Requires</em>:  <tt>sizeof...(Types) == 2</tt>. <del><tt>is_constructible&lt;<em>T<sub>0</sub></em>, const U1&amp;&gt;::value</tt> is true for 
the first type <tt><em>T<sub>0</sub></em></tt> in <tt>Types</tt> and <tt>is_constructible&lt;<em>T<sub>1</sub></em>, const U2&amp;&gt;::value</tt> 
is true for the second type <tt><em>T<sub>1</sub></em></tt> in <tt>Types</tt>.</del>
<p/>
-22- <em>Effects</em>: <ins>The constructor initializes</ins><del>Constructs</del> the first element with <tt>u.first</tt> and the second element with <tt>u.second</tt>.
<p/>
-23- <em>Remark<ins>s</ins></em>: This constructor shall not participate in overload resolution unless <del><tt>const U1&amp;</tt> 
is implicitly convertible to <tt><em>T<sub>0</sub></em></tt> and <tt>const U2&amp;</tt> is implicitly convertible to <tt><em>T<sub>1</sub></em></tt></del>
	<ins><tt>is_constructible&lt;<em>T<sub>0</sub></em>, const U1&amp;&gt;::value</tt> is <tt>true</tt> and 
	<tt>is_constructible&lt;<em>T<sub>1</sub></em>, const U2&amp;&gt;::value</tt> is <tt>true</tt>. The constructor is explicit if and only if 
	<tt>is_convertible&lt;const U1&amp;, <em>T<sub>0</sub></em>&gt;::value</tt> is <tt>false</tt> or 
	<tt>is_convertible&lt;const U2&amp;, <em>T<sub>1</sub></em>&gt;::value</tt> is <tt>false</tt></ins>.
</p>
</blockquote></blockquote>
</li>
<li><p>Change 20.4.2.1 [tuple.cnstr] around p24 as indicated:</p>
<blockquote><pre>
template &lt;class U1, class U2&gt; <ins><i>EXPLICIT</i></ins> constexpr tuple(pair&lt;U1, U2&gt;&amp;&amp; u);
</pre><blockquote><p>
-24- <em>Requires</em>: <tt>sizeof...(Types) == 2</tt>. <del><tt>is_constructible&lt;<em>T<sub>0</sub></em>, U1&amp;&amp;&gt;::value</tt> is true for 
the first type <tt><em>T<sub>0</sub></em></tt> in <tt>Types</tt> and <tt>is_constructible&lt;<em>T<sub>1</sub></em>, U2&amp;&amp;&gt;::value</tt> 
is true for the second type <tt><em>T<sub>1</sub></em></tt> in <tt>Types</tt>.</del>
<p/>
-25- <em>Effects</em>: <ins>The constructor i</ins><del>I</del>nitializes the first element with 
<tt>std::forward&lt;U1&gt;(u.first)</tt> and the second element with <tt>std::forward&lt;U2&gt;(u.second)</tt>.
<p/>
-26- <em>Remark<ins>s</ins></em>: This constructor shall not participate in overload resolution unless <del><tt>U1</tt> is implicitly 
convertible to <tt><em>T<sub>0</sub></em></tt> and <tt>U2</tt> is implicitly convertible to <tt><em>T<sub>1</sub></em></tt></del>
	<ins><tt>is_constructible&lt;<em>T<sub>0</sub></em>, U1&amp;&amp;&gt;::value</tt> is <tt>true</tt> and 
	<tt>is_constructible&lt;<em>T<sub>1</sub></em>, U2&amp;&amp;&gt;::value</tt> is <tt>true</tt>. The constructor is explicit if and only 
	if <tt>is_convertible&lt;U1&amp;&amp;, <em>T<sub>0</sub></em>&gt;::value</tt> is <tt>false</tt> 
	or <tt>is_convertible&lt;U2&amp;&amp;, <em>T<sub>1</sub></em>&gt;::value</tt> is <tt>false</tt></ins>.
</p>
</blockquote></blockquote>
</li>

<li><p>Change 20.4.2.1 [tuple.cnstr] around p27 as indicated:</p>
<blockquote><pre>
template &lt;class Alloc&gt;
  tuple(allocator_arg_t, const Alloc&amp; a);
template &lt;class Alloc&gt;
  <ins><i>EXPLICIT</i></ins> tuple(allocator_arg_t, const Alloc&amp; a, const Types&amp;...);
template &lt;class Alloc, class... UTypes&gt;
  <ins><i>EXPLICIT</i></ins> tuple(allocator_arg_t, const Alloc&amp; a, UTypes&amp;&amp;...);
template &lt;class Alloc&gt;
  tuple(allocator_arg_t, const Alloc&amp; a, const tuple&amp;);
template &lt;class Alloc&gt;
  tuple(allocator_arg_t, const Alloc&amp; a, tuple&amp;&amp;);
template &lt;class Alloc, class... UTypes&gt;
  <ins><i>EXPLICIT</i></ins> tuple(allocator_arg_t, const Alloc&amp; a, const tuple&lt;UTypes...&gt;&amp;);
template &lt;class Alloc, class... UTypes&gt;
  <ins><i>EXPLICIT</i></ins> tuple(allocator_arg_t, const Alloc&amp; a, tuple&lt;UTypes...&gt;&amp;&amp;);
template &lt;class Alloc, class U1, class U2&gt;
  <ins><i>EXPLICIT</i></ins> tuple(allocator_arg_t, const Alloc&amp; a, const pair&lt;U1, U2&gt;&amp;);
template &lt;class Alloc, class U1, class U2&gt;
  <ins><i>EXPLICIT</i></ins> tuple(allocator_arg_t, const Alloc&amp; a, pair&lt;U1, U2&gt;&amp;&amp;);
</pre><blockquote><p>
-27- <em>Requires</em>: <tt>Alloc</tt> shall meet the requirements for an <tt>Allocator</tt> (17.6.3.5).
<p/>
-28- <em>Effects</em>: Equivalent to the preceding constructors except that each element is constructed with uses-allocator
construction (20.7.7.2).
</p>
</blockquote></blockquote>
</li>

</ol>
<p>
</p>

<h2><a name="ImplHint"></a>Implementation Hint</h2>

<p>
The following example presents how to constrain even non-template functions such as the constructors
that directly take the element types.
</p>

<blockquote><pre>
template&lt;class T1, class T2&gt;
struct pair {

  [&hellip;]

  template&lt;class U1 = T1, class U2 = T2,
    typename enable_if&lt;
      is_copy_constructible&lt;U1&gt;::value &amp;&amp; is_copy_constructible&lt;U2&gt;::value &amp;&amp;
      is_convertible&lt;const U1&amp;, U1&gt;::value &amp;&amp; is_convertible&lt;const U2&amp;, U2&gt;::value
    , bool&gt;::type = false
  &gt;
  constexpr pair(const T1&amp;, const T2&amp;);

  template&lt;class U1 = T1, class U2 = T2,
    typename enable_if&lt;
      is_copy_constructible&lt;U1&gt;::value &amp;&amp; is_copy_constructible&lt;U2&gt;::value &amp;&amp;
      !(is_convertible&lt;const U1&amp;, U1&gt;::value &amp;&amp; is_convertible&lt;const U2&amp;, U2&gt;::value)
    , bool&gt;::type = false
  &gt;
  explicit constexpr pair(const T1&amp;, const T2&amp;);
};
</pre></blockquote>

<h2><a name="Akn"></a>Acknowledgements</h2>
<p>
I would like to thank Howard Hinnant for his very helpful discussions and comments during reviews of this paper and for
his motivating example. Thanks also to Jonathan Wakely for his review that improved this proposal to a large extend.
Thanks as well go to Mike Spertus for helping to improve the rationale.
</p>
</body>
</html>