public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [v3 PATCH] Implement N4387 and LWG 2367
@ 2015-06-07  6:53 Ville Voutilainen
  2015-06-07  8:13 ` Marc Glisse
  2015-06-08 15:41 ` Martin Sebor
  0 siblings, 2 replies; 11+ messages in thread
From: Ville Voutilainen @ 2015-06-07  6:53 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2180 bytes --]

This patch implements the so-called conditionally-explicit constructors
for tuple and pair, and also constrains the default constructors of tuple and
pair. The patch does not try to implement the part in N4387 that allows
constructing tuples from shorter packs than the tuple's element count,
I suggest we look at that separately. The constraints involve fair amounts
of evil black magic, but they do the job. Chances are they can be simplified,
but I again suggest we look at that separately.

Tested on Linux-PPC64.

Patch gzipped since it's 50kB otherwise. :)

2015-06-07  Ville Voutilainen  <ville.voutilainen@gmail.com>
    Implement N4387, "improving pair and tuple" and
    LWG 2367, "pair and tuple are not correctly implemented for
    is_constructible with no args".
    * include/bits/stl_pair.h (_ConstructiblePair,
    _ImplicitlyConvertiblePair, _MoveConstructiblePair,
    _ImplicitlyMoveConvertiblePair): New.
    * include/bits/stl_pair.h (pair()): Constrain it.
    * include/bits/stl_pair.h (pair(const _T1&, const _T2&),
    pair(const pair<_U1, _U2>&), pair(_U1&&, const _T2&),
    pair(const _T1&, _U2&&), pair(_U1&&, _U2&&),
    pair(pair<_U1, _U2>&&)): Make conditionally explicit.
    * include/std/tuple (_TC, _TC2): New.
    * include/std/tuple (tuple()): Constrain it.
    * include/std/tuple (tuple(const _UElements&...),
    tuple(_UElements&&...), tuple(const tuple<_UElements...>&),
    tuple(tuple<_UElements...>&&),
    tuple(allocator_arg_t, const _Alloc&, const _UElements&...),
    tuple(allocator_arg_t, const _Alloc&, _UElements&&...),
    tuple(allocator_arg_t, const _Alloc&, const tuple<_UElements...>&),
    tuple(allocator_arg_t, const _Alloc&, tuple<_UElements...>&&),
    tuple(const pair<_U1, _U2>&),
    tuple(pair<_U1, _U2>&&),
    tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&),
    tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&&)): Make
    conditionally explicit.
    * testsuite/20_util/pair/cons/explicit_construct.cc: New.
    * testsuite/20_util/pair/requirements/dr2367.cc: New.
    * testsuite/20_util/tuple/cons/explicit_construct.cc: New.
    * testsuite/20_util/tuple/requirements/dr2367.cc: New.

[-- Attachment #2: explicit-tuple-pair.diff.gz --]
[-- Type: application/x-gzip, Size: 5569 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [v3 PATCH] Implement N4387 and LWG 2367
  2015-06-07  6:53 [v3 PATCH] Implement N4387 and LWG 2367 Ville Voutilainen
@ 2015-06-07  8:13 ` Marc Glisse
  2015-06-07  8:33   ` Ville Voutilainen
  2015-06-08 15:41 ` Martin Sebor
  1 sibling, 1 reply; 11+ messages in thread
From: Marc Glisse @ 2015-06-07  8:13 UTC (permalink / raw)
  To: Ville Voutilainen; +Cc: libstdc++, gcc-patches

On Sun, 7 Jun 2015, Ville Voutilainen wrote:

-      explicit
-      constexpr tuple(const _Elements&... __elements)
+      template<typename... _UElements, typename
+        enable_if<__and_<is_same<const _Elements&,
+                                    const _UElements&>...>::value
+                  && _TC<(sizeof...(_Elements) == sizeof...(_UElements)),
+                            _Elements...>::template
+                  _ConstructibleTuple<_UElements...>()
+                  && _TC<(sizeof...(_Elements) == sizeof...(_UElements)),
+                            _Elements...>::template
+                  _ImplicitlyConvertibleTuple<_UElements...>()
+                  && !_TC<(sizeof...(_Elements) == sizeof...(_UElements)),
+                            _Elements...>::template
+                  _MoveConstructibleTuple<_UElements...>()
+                  && !_TC<(sizeof...(_Elements) == sizeof...(_UElements)),
+                            _Elements...>::template
+                  _ImplicitlyMoveConvertibleTuple<_UElements...>()
+                  && (sizeof...(_Elements) >= 1),
+        bool>::type=true>
+      constexpr tuple(const _UElements&... __elements)
        : _Inherited(__elements...) { }

Since the paper does not mention looking at _MoveConstructibleTuple or
_ImplicitlyMoveConvertibleTuple here, could you add a comment explaining
why that is needed?

Does the following code still compile with your patch?
struct A { int a,b; };
std::tuple<int,int,A> a(3,4,{1,2});

IMO the parts with is_default_constructible point to a core issue, we 
should not have to duplicate information, especially in such a convoluted 
way. But I guess that has lower priority than noexcept(auto), and I 
haven't yet looked if concepts will help.

You use a lot: typename enable_if<X, bool>::type=true
while the current code seems to favor: class=typename enable_if<X>::type.
I don't really care which one is used, but it is easier to read when the 
style is consistent through the library.

Introducing
typename _XXX = _TC<(sizeof...(_Elements) == sizeof...(_UElements)), _Elements...>
and then using _XXX::template thing() might give less clutter when you 
have to repeat it 4 times.

-- 
Marc Glisse

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [v3 PATCH] Implement N4387 and LWG 2367
  2015-06-07  8:13 ` Marc Glisse
@ 2015-06-07  8:33   ` Ville Voutilainen
  2015-06-07  8:49     ` Ville Voutilainen
  0 siblings, 1 reply; 11+ messages in thread
From: Ville Voutilainen @ 2015-06-07  8:33 UTC (permalink / raw)
  To: libstdc++; +Cc: gcc-patches

On 7 June 2015 at 09:53, Marc Glisse <marc.glisse@inria.fr> wrote:
> Since the paper does not mention looking at _MoveConstructibleTuple or
> _ImplicitlyMoveConvertibleTuple here, could you add a comment explaining
> why that is needed?

Sure.

> Does the following code still compile with your patch?
> struct A { int a,b; };
> std::tuple<int,int,A> a(3,4,{1,2});

No. :/ And we have no test for it.. I'll need to look at that.

> IMO the parts with is_default_constructible point to a core issue, we should
> not have to duplicate information, especially in such a convoluted way. But
> I guess that has lower priority than noexcept(auto), and I haven't yet
> looked if concepts will help.

Concepts would help a lot, but being able to use them in a library
implementation
is some ways off.

> You use a lot: typename enable_if<X, bool>::type=true
> while the current code seems to favor: class=typename enable_if<X>::type.
> I don't really care which one is used, but it is easier to read when the
> style is consistent through the library.

It's not a style issue. That template parameter needs to be a non-type one,
otherwise the overloads are ambiguous.

> Introducing
> typename _XXX = _TC<(sizeof...(_Elements) == sizeof...(_UElements)),
> _Elements...>
> and then using _XXX::template thing() might give less clutter when you have
> to repeat it 4 times.

Sounds good, I'll give it a spin.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [v3 PATCH] Implement N4387 and LWG 2367
  2015-06-07  8:33   ` Ville Voutilainen
@ 2015-06-07  8:49     ` Ville Voutilainen
  2015-06-07  8:50       ` Ville Voutilainen
  2015-06-07 11:37       ` Marc Glisse
  0 siblings, 2 replies; 11+ messages in thread
From: Ville Voutilainen @ 2015-06-07  8:49 UTC (permalink / raw)
  To: libstdc++; +Cc: gcc-patches

On 7 June 2015 at 11:12, Ville Voutilainen <ville.voutilainen@gmail.com> wrote:
>> Does the following code still compile with your patch?
>> struct A { int a,b; };
>> std::tuple<int,int,A> a(3,4,{1,2});
>
> No. :/ And we have no test for it.. I'll need to look at that.

Ahem, yes, this is because the constructor that used to take _Elements
now takes _UElements. I can change it back to take _Elements, because
the technique that the default constructors use allow making the signature
dependent enough that it will sfinae correctly.

>> You use a lot: typename enable_if<X, bool>::type=true
>> while the current code seems to favor: class=typename enable_if<X>::type.
>> I don't really care which one is used, but it is easier to read when the
>> style is consistent through the library.
> It's not a style issue. That template parameter needs to be a non-type one,
> otherwise the overloads are ambiguous.

...and I think it doesn't necessarily need to be non-type, I think it can be
made to work with a type parameter that is enable_if<X, true_type>
and enable_if<X, false_type> for the mutually-exclusive overloads.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [v3 PATCH] Implement N4387 and LWG 2367
  2015-06-07  8:49     ` Ville Voutilainen
@ 2015-06-07  8:50       ` Ville Voutilainen
  2015-06-07 11:37       ` Marc Glisse
  1 sibling, 0 replies; 11+ messages in thread
From: Ville Voutilainen @ 2015-06-07  8:50 UTC (permalink / raw)
  To: libstdc++; +Cc: gcc-patches

On 7 June 2015 at 11:33, Ville Voutilainen <ville.voutilainen@gmail.com> wrote:
>>> You use a lot: typename enable_if<X, bool>::type=true
>>> while the current code seems to favor: class=typename enable_if<X>::type.
>>> I don't really care which one is used, but it is easier to read when the
>>> style is consistent through the library.
>> It's not a style issue. That template parameter needs to be a non-type one,
>> otherwise the overloads are ambiguous.
> ...and I think it doesn't necessarily need to be non-type, I think it can be
> made to work with a type parameter that is enable_if<X, true_type>
> and enable_if<X, false_type> for the mutually-exclusive overloads.

Except that no, it can't. It really needs to be a non-type parameter. :P

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [v3 PATCH] Implement N4387 and LWG 2367
  2015-06-07  8:49     ` Ville Voutilainen
  2015-06-07  8:50       ` Ville Voutilainen
@ 2015-06-07 11:37       ` Marc Glisse
  1 sibling, 0 replies; 11+ messages in thread
From: Marc Glisse @ 2015-06-07 11:37 UTC (permalink / raw)
  To: Ville Voutilainen; +Cc: libstdc++, gcc-patches

On Sun, 7 Jun 2015, Ville Voutilainen wrote:

> On 7 June 2015 at 11:12, Ville Voutilainen <ville.voutilainen@gmail.com> wrote:
>>> Does the following code still compile with your patch?
>>> struct A { int a,b; };
>>> std::tuple<int,int,A> a(3,4,{1,2});
>>
>> No. :/ And we have no test for it.. I'll need to look at that.
>
> Ahem, yes, this is because the constructor that used to take _Elements
> now takes _UElements. I can change it back to take _Elements, because
> the technique that the default constructors use allow making the signature
> dependent enough that it will sfinae correctly.

Yes.

>>> You use a lot: typename enable_if<X, bool>::type=true
>>> while the current code seems to favor: class=typename enable_if<X>::type.
>>> I don't really care which one is used, but it is easier to read when the
>>> style is consistent through the library.
>> It's not a style issue. That template parameter needs to be a non-type one,
>> otherwise the overloads are ambiguous.

Ah, I had overlooked that. I have seen several work-arounds for this 
issue, but I don't remember this one, it seems nice.

-- 
Marc Glisse

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [v3 PATCH] Implement N4387 and LWG 2367
  2015-06-07  6:53 [v3 PATCH] Implement N4387 and LWG 2367 Ville Voutilainen
  2015-06-07  8:13 ` Marc Glisse
@ 2015-06-08 15:41 ` Martin Sebor
  2015-06-08 15:56   ` Ville Voutilainen
  1 sibling, 1 reply; 11+ messages in thread
From: Martin Sebor @ 2015-06-08 15:41 UTC (permalink / raw)
  To: Ville Voutilainen, libstdc++, gcc-patches

>      * include/std/tuple

In the hunk below, should the sizes_match template parameter
be privatized (since it isn't part of the public interface)?
Or perhaps even removed if it's not used?

Martin

@ -457,6 +457,73 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        }
      };

+
+  // Concept utility functions
+  template <bool sizes_match, typename... _Elements>
+  struct _TC

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [v3 PATCH] Implement N4387 and LWG 2367
  2015-06-08 15:41 ` Martin Sebor
@ 2015-06-08 15:56   ` Ville Voutilainen
  2015-06-08 16:16     ` Ville Voutilainen
  0 siblings, 1 reply; 11+ messages in thread
From: Ville Voutilainen @ 2015-06-08 15:56 UTC (permalink / raw)
  To: Martin Sebor; +Cc: libstdc++, gcc-patches

On 8 June 2015 at 18:37, Martin Sebor <msebor@redhat.com> wrote:
> In the hunk below, should the sizes_match template parameter
> be privatized (since it isn't part of the public interface)?
> Or perhaps even removed if it's not used?

Yes, it should be uglified, thanks.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [v3 PATCH] Implement N4387 and LWG 2367
  2015-06-08 15:56   ` Ville Voutilainen
@ 2015-06-08 16:16     ` Ville Voutilainen
  2015-06-14  7:07       ` Ville Voutilainen
  0 siblings, 1 reply; 11+ messages in thread
From: Ville Voutilainen @ 2015-06-08 16:16 UTC (permalink / raw)
  To: Martin Sebor; +Cc: libstdc++, gcc-patches

On 8 June 2015 at 18:53, Ville Voutilainen <ville.voutilainen@gmail.com> wrote:
> On 8 June 2015 at 18:37, Martin Sebor <msebor@redhat.com> wrote:
>> In the hunk below, should the sizes_match template parameter
>> be privatized (since it isn't part of the public interface)?
>> Or perhaps even removed if it's not used?
>
> Yes, it should be uglified, thanks.

Ahem, yes, actually removed since it's there only to be specialized.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [v3 PATCH] Implement N4387 and LWG 2367
  2015-06-08 16:16     ` Ville Voutilainen
@ 2015-06-14  7:07       ` Ville Voutilainen
  2015-06-30 13:28         ` Jonathan Wakely
  0 siblings, 1 reply; 11+ messages in thread
From: Ville Voutilainen @ 2015-06-14  7:07 UTC (permalink / raw)
  To: gcc-patches, libstdc++

[-- Attachment #1: Type: text/plain, Size: 3424 bytes --]

On 8 June 2015 at 19:01, Ville Voutilainen <ville.voutilainen@gmail.com> wrote:
>> Yes, it should be uglified, thanks.
> Ahem, yes, actually removed since it's there only to be specialized.

Another round! The new patch
- makes sure not to change non-deduced parameters to deduced ones, and adds
tests for that.
- removes the name of the bool non-type template parameter for the 'concepts'.
- introduces shortcuts for making the use of the 'concepts' more readable.
- changes library tag types into non-default-constructible ones.
Without this, we
can run into an ambiguity between the constructor template that takes
(const _T1&, const _T2&)
and the one that takes (allocator_arg_t, Alloc), when the call site
calls it with ({}, somethingelse).
We could avoid that by just not doing that in the library
(experimental string searchers do that),
but it's just daft to allow default-constructing a library tag type. I
have filed an LWG issue to
fix all tag types, but this patch doesn't yet touch nothrow_t and
optional's in_place_t. I expect
to submit follow-up patches for that.

Tested on Linux-PPC64.

2015-06-13  Ville Voutilainen  <ville.voutilainen@gmail.com>
    Implement N4387, "improving pair and tuple" and
    LWG 2367, "pair and tuple are not correctly implemented for
    is_constructible with no args". Also make the standard tag types
    non-default-constructible. std::nothrow_t not taken care
    of yet in that regard, nor std::experimental::optional's
    in_place_t.
    * include/bits/stl_pair.h (piecewise_construct_t,
    piecewise_construct): Make non-default-constructible and adjust.
    * include/bits/stl_pair.h (_ConstructiblePair,
    _ImplicitlyConvertiblePair, _MoveConstructiblePair,
    _ImplicitlyMoveConvertiblePair): New.
    * include/bits/stl_pair.h (pair()): Constrain it.
    * include/bits/stl_pair.h (pair(const _T1&, const _T2&),
    pair(const pair<_U1, _U2>&), pair(_U1&&, const _T2&),
    pair(const _T1&, _U2&&), pair(_U1&&, _U2&&),
    pair(pair<_U1, _U2>&&)): Make conditionally explicit.
    * include/bits/uses_allocator.h (allocator_arg_t,
    allocator_arg): Make non-default-constructible and adjust.
    * include/std/mutex (defer_lock_t, defer_lock,
    try_to_lock_t, try_to_lock, adopt_lock_t, adopt_lock):
    Make non-default-constructible and adjust.
    * include/std/tuple (_TC, tuple::_TC2, tuple::TCC, tuple::TMC): New.
    * include/std/tuple (tuple()): Constrain it.
    * include/std/tuple (tuple(const _UElements&...),
    tuple(_UElements&&...), tuple(const tuple<_UElements...>&),
    tuple(tuple<_UElements...>&&),
    tuple(allocator_arg_t, const _Alloc&, const _UElements&...),
    tuple(allocator_arg_t, const _Alloc&, _UElements&&...),
    tuple(allocator_arg_t, const _Alloc&, const tuple<_UElements...>&),
    tuple(allocator_arg_t, const _Alloc&, tuple<_UElements...>&&),
    tuple(const pair<_U1, _U2>&),
    tuple(pair<_U1, _U2>&&),
    tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&),
    tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&&)): Make
    conditionally explicit.
    * src/c++11/compatibility-thread-c++0x.cc: Adjust.
    * testsuite/20_util/pair/cons/explicit_construct.cc: New.
    * estsuite/20_util/pair/piecewise.cc: Adjust.
    * testsuite/20_util/pair/requirements/dr2367.cc: New.
    * testsuite/20_util/tuple/cons/explicit_construct.cc: New.
    * testsuite/20_util/tuple/requirements/dr2367.cc: New.

[-- Attachment #2: conditional-explicit4.diff.gz --]
[-- Type: application/x-gzip, Size: 6887 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [v3 PATCH] Implement N4387 and LWG 2367
  2015-06-14  7:07       ` Ville Voutilainen
@ 2015-06-30 13:28         ` Jonathan Wakely
  0 siblings, 0 replies; 11+ messages in thread
From: Jonathan Wakely @ 2015-06-30 13:28 UTC (permalink / raw)
  To: Ville Voutilainen; +Cc: gcc-patches, libstdc++

[-- Attachment #1: Type: text/plain, Size: 1545 bytes --]

On 13/06/15 21:05 +0300, Ville Voutilainen wrote:
>Another round! The new patch
>- makes sure not to change non-deduced parameters to deduced ones, and adds
>tests for that.
>- removes the name of the bool non-type template parameter for the 'concepts'.
>- introduces shortcuts for making the use of the 'concepts' more readable.

These bits are lovely jubbly.

>- changes library tag types into non-default-constructible ones.
>Without this, we
>can run into an ambiguity between the constructor template that takes
>(const _T1&, const _T2&)
>and the one that takes (allocator_arg_t, Alloc), when the call site
>calls it with ({}, somethingelse).
>We could avoid that by just not doing that in the library
>(experimental string searchers do that),
>but it's just daft to allow default-constructing a library tag type. I
>have filed an LWG issue to
>fix all tag types, but this patch doesn't yet touch nothrow_t and
>optional's in_place_t. I expect
>to submit follow-up patches for that.

I agree that default-constructing tag types doesn't make sense when we
have named constants to use. I also think it's a real pain in the
posterior that tuple<T,U>( {}, T{} } is ambiguous, but I'm not
comfortable with making all those tag types non-default constructible
until we get an indication how LWG feel about the proposal.

So I've removed that part of the patch and "fixed" the searcher that
used {} and became ambiguous. I have a follow-up patch coming that
will prevent the ambiguities differently.

Tested ppc64le-linux and committed to trunk.


[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 54964 bytes --]

commit b80baac2fa84492f90e9c4137190330cf7c53fee
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Jun 29 15:07:36 2015 +0100

    2015-06-30  Ville Voutilainen  <ville.voutilainen@gmail.com>
    
    	Implement N4387, "Improving pair and tuple", and LWG 2367.
    
    	* include/bits/stl_pair.h (_ConstructiblePair,
    	_ImplicitlyConvertiblePair, _MoveConstructiblePair,
    	_ImplicitlyMoveConvertiblePair): New.
    	(pair()): Constrain it.
    	(pair(const _T1&, const _T2&), pair(const pair<_U1, _U2>&),
    	pair(_U1&&, const _T2&), pair(const _T1&, _U2&&), pair(_U1&&, _U2&&),
    	pair(pair<_U1, _U2>&&)): Make conditionally explicit.
    	* include/std/tuple (_TC, tuple::_TC2, tuple::TCC, tuple::TMC): New.
    	(tuple()): Constrain it.
    	(tuple(const _UElements&...), tuple(_UElements&&...),
    	tuple(const tuple<_UElements...>&), tuple(tuple<_UElements...>&&),
    	tuple(allocator_arg_t, const _Alloc&, const _UElements&...),
    	tuple(allocator_arg_t, const _Alloc&, _UElements&&...),
    	tuple(allocator_arg_t, const _Alloc&, const tuple<_UElements...>&),
    	tuple(allocator_arg_t, const _Alloc&, tuple<_UElements...>&&),
    	tuple(const pair<_U1, _U2>&), tuple(pair<_U1, _U2>&&),
    	tuple(allocator_arg_t, const _Alloc&, const pair<_U1, _U2>&),
    	tuple(allocator_arg_t, const _Alloc&, pair<_U1, _U2>&&)): Make
    	conditionally explicit.
    	* include/experimental/functional (__boyer_moore_array_base): Name
    	array type explicitly instead of using an empty braced-init-list.
    	* testsuite/20_util/pair/cons/explicit_construct.cc: New.
    	* testsuite/20_util/pair/piecewise.cc: Use piecewise_construct.
    	* testsuite/20_util/pair/requirements/dr2367.cc: New.
    	* testsuite/20_util/tuple/cons/explicit_construct.cc: New.
    	* testsuite/20_util/tuple/requirements/dr2367.cc: New.

diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h
index 490b005..6672ecb 100644
--- a/libstdc++-v3/include/bits/stl_pair.h
+++ b/libstdc++-v3/include/bits/stl_pair.h
@@ -84,6 +84,38 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template<std::size_t...>
     struct _Index_tuple;
+
+  // Concept utility functions, reused in conditionally-explicit
+  // constructors.
+  template <typename _T1, typename _T2, typename _U1, typename _U2>
+  constexpr bool _ConstructiblePair()
+  {
+    return __and_<is_constructible<_T1, const _U1&>,
+		  is_constructible<_T2, const _U2&>>::value;
+  }
+
+  template <typename _T1, typename _T2, typename _U1, typename _U2>
+  constexpr bool _ImplicitlyConvertiblePair()
+  {
+    return __and_<is_convertible<const _U1&, _T1>,
+		  is_convertible<const _U2&, _T2>>::value;
+  }
+
+  template <typename _T1, typename _T2, typename _U1, typename _U2>
+  constexpr bool _MoveConstructiblePair()
+  {
+    return __and_<is_constructible<_T1, _U1&&>,
+		  is_constructible<_T2, _U2&&>>::value;
+  }
+
+  template <typename _T1, typename _T2, typename _U1, typename _U2>
+  constexpr bool _ImplicitlyMoveConvertiblePair()
+  {
+    return __and_<is_convertible<_U1&&, _T1>,
+		  is_convertible<_U2&&, _T2>>::value;
+  }
+
+
 #endif
 
  /**
@@ -105,52 +137,136 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // 265.  std::pair::pair() effects overly restrictive
       /** The default constructor creates @c first and @c second using their
        *  respective default constructors.  */
+#if __cplusplus >= 201103L
+      template <typename _U1 = _T1,
+                typename _U2 = _T2,
+                typename enable_if<__and_<
+                                     is_default_constructible<_U1>,
+                                     is_default_constructible<_U2>>
+                                   ::value, bool>::type = true>
+#endif
       _GLIBCXX_CONSTEXPR pair()
       : first(), second() { }
 
       /** Two objects may be passed to a @c pair constructor to be copied.  */
-      _GLIBCXX_CONSTEXPR pair(const _T1& __a, const _T2& __b)
+#if __cplusplus < 201103L
+      pair(const _T1& __a, const _T2& __b)
+      : first(__a), second(__b) { }
+#else
+      template<typename _U1 = _T1, typename _U2=_T2, typename
+                enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>()
+                         && _ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(),
+                         bool>::type=true>
+      constexpr pair(const _T1& __a, const _T2& __b)
       : first(__a), second(__b) { }
 
+       template<typename _U1 = _T1, typename _U2=_T2, typename
+	       enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>()
+                         && !_ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(),
+                         bool>::type=false>
+      explicit constexpr pair(const _T1& __a, const _T2& __b)
+      : first(__a), second(__b) { }
+#endif
+
       /** There is also a templated copy ctor for the @c pair class itself.  */
 #if __cplusplus < 201103L
       template<class _U1, class _U2>
 	pair(const pair<_U1, _U2>& __p)
 	: first(__p.first), second(__p.second) { }
 #else
-      template<class _U1, class _U2, class = typename
-	       enable_if<__and_<is_convertible<const _U1&, _T1>,
-				is_convertible<const _U2&, _T2>>::value>::type>
-	constexpr pair(const pair<_U1, _U2>& __p)
+      template<class _U1, class _U2, typename
+	       enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>()
+                         && _ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(),
+                         bool>::type=true>
+        constexpr pair(const pair<_U1, _U2>& __p)
+        : first(__p.first), second(__p.second) { }
+
+      template<class _U1, class _U2, typename
+               enable_if<_ConstructiblePair<_T1, _T2, _U1, _U2>()
+                         && !_ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(),
+                         bool>::type=false>
+	explicit constexpr pair(const pair<_U1, _U2>& __p)
 	: first(__p.first), second(__p.second) { }
 
       constexpr pair(const pair&) = default;
       constexpr pair(pair&&) = default;
 
       // DR 811.
-      template<class _U1, class = typename
-	       enable_if<is_convertible<_U1, _T1>::value>::type>
-	constexpr pair(_U1&& __x, const _T2& __y)
-	: first(std::forward<_U1>(__x)), second(__y) { }
-
-      template<class _U2, class = typename
-	       enable_if<is_convertible<_U2, _T2>::value>::type>
-	constexpr pair(const _T1& __x, _U2&& __y)
-	: first(__x), second(std::forward<_U2>(__y)) { }
-
-      template<class _U1, class _U2, class = typename
-	       enable_if<__and_<is_convertible<_U1, _T1>,
-				is_convertible<_U2, _T2>>::value>::type>
+      template<class _U1, typename
+               enable_if<_ConstructiblePair<_T2, _T2, _T2, _T2>()
+                         && _MoveConstructiblePair<_T1, _T2, _U1, _T2>()
+                         && _ImplicitlyConvertiblePair<_T2, _T2, _T2, _T2>()
+                         && _ImplicitlyMoveConvertiblePair<_T1, _T2,
+							  _U1, _T2>(),
+                         bool>::type=true>
+       constexpr pair(_U1&& __x, const _T2& __y)
+       : first(std::forward<_U1>(__x)), second(__y) { }
+
+      template<class _U1, typename
+               enable_if<_ConstructiblePair<_T2, _T2, _T2, _T2>()
+                         && _MoveConstructiblePair<_T1, _T2, _U1, _T2>()
+                         && (!_ImplicitlyConvertiblePair<_T2, _T2, _T2, _T2>()
+                             || !_ImplicitlyMoveConvertiblePair<_T1, _T2,
+                                                                _U1, _T2>()),
+                         bool>::type=false>
+       explicit constexpr pair(_U1&& __x, const _T2& __y)
+       : first(std::forward<_U1>(__x)), second(__y) { }
+
+      template<class _U2, typename
+               enable_if<_ConstructiblePair<_T1, _T1, _T1, _T1>()
+                         && _MoveConstructiblePair<_T1, _T2, _T1, _U2>()
+                         && _ImplicitlyConvertiblePair<_T1, _T1, _T1, _T1>()
+                         && _ImplicitlyMoveConvertiblePair<_T1, _T2,
+                                                           _T1, _U2>(),
+                         bool>::type=true>
+       constexpr pair(const _T1& __x, _U2&& __y)
+       : first(__x), second(std::forward<_U2>(__y)) { }
+
+      template<class _U2, typename
+               enable_if<_ConstructiblePair<_T1, _T1, _T1, _T1>()
+                         && _MoveConstructiblePair<_T1, _T2, _T1, _U2>()
+                         && (!_ImplicitlyConvertiblePair<_T1, _T1, _T1, _T1>()
+                             || !_ImplicitlyMoveConvertiblePair<_T1, _T2,
+                                                                _T1, _U2>()),
+                         bool>::type=false>
+       explicit pair(const _T1& __x, _U2&& __y)
+       : first(__x), second(std::forward<_U2>(__y)) { }
+
+      template<class _U1, class _U2, typename
+	       enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>()
+                         && _ImplicitlyMoveConvertiblePair<_T1, _T2,
+							   _U1, _U2>(),
+                         bool>::type=true>
 	constexpr pair(_U1&& __x, _U2&& __y)
 	: first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { }
 
-      template<class _U1, class _U2, class = typename
-	       enable_if<__and_<is_convertible<_U1, _T1>,
-				is_convertible<_U2, _T2>>::value>::type>
+      template<class _U1, class _U2, typename
+	       enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>()
+                         && !_ImplicitlyMoveConvertiblePair<_T1, _T2,
+							    _U1, _U2>(),
+                         bool>::type=false>
+	explicit constexpr pair(_U1&& __x, _U2&& __y)
+	: first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { }
+
+
+      template<class _U1, class _U2, typename
+	       enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>()
+                         && _ImplicitlyMoveConvertiblePair<_T1, _T2,
+							   _U1, _U2>(),
+                         bool>::type=true>
 	constexpr pair(pair<_U1, _U2>&& __p)
 	: first(std::forward<_U1>(__p.first)),
 	  second(std::forward<_U2>(__p.second)) { }
 
+      template<class _U1, class _U2, typename
+	       enable_if<_MoveConstructiblePair<_T1, _T2, _U1, _U2>()
+                         && !_ImplicitlyMoveConvertiblePair<_T1, _T2,
+							   _U1, _U2>(),
+                         bool>::type=false>
+	explicit constexpr pair(pair<_U1, _U2>&& __p)
+	: first(std::forward<_U1>(__p.first)),
+	  second(std::forward<_U2>(__p.second)) { }
+
       template<typename... _Args1, typename... _Args2>
         pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>);
 
diff --git a/libstdc++-v3/include/experimental/functional b/libstdc++-v3/include/experimental/functional
index 0472f59..c6b9800 100644
--- a/libstdc++-v3/include/experimental/functional
+++ b/libstdc++-v3/include/experimental/functional
@@ -124,7 +124,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       template<typename _RAIter, typename _Unused>
 	__boyer_moore_array_base(_RAIter __pat, size_t __patlen,
 				 _Unused&&, _Pred&& __pred)
-	: _M_bad_char{ {}, std::move(__pred) }
+	: _M_bad_char{ std::array<_Tp, _Len>{}, std::move(__pred) }
 	{
 	  std::get<0>(_M_bad_char).fill(__patlen);
 	  if (__patlen > 0)
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 0504012..59b992a 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -457,63 +457,236 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
     };
 
+
+  // Concept utility functions, reused in conditionally-explicit
+  // constructors.
+  template<bool, typename... _Elements>
+  struct _TC
+  {
+    template<typename... _UElements>
+    static constexpr bool _ConstructibleTuple()
+    {
+      return __and_<is_constructible<_Elements, const _UElements&>...>::value;
+    }
+
+    template<typename... _UElements>
+    static constexpr bool _ImplicitlyConvertibleTuple()
+    {
+      return __and_<is_convertible<const _UElements&, _Elements>...>::value;
+    }
+
+    template<typename... _UElements>
+    static constexpr bool _MoveConstructibleTuple()
+    {
+      return __and_<is_constructible<_Elements, _UElements&&>...>::value;
+    }
+
+    template<typename... _UElements>
+    static constexpr bool _ImplicitlyMoveConvertibleTuple()
+    {
+      return __and_<is_convertible<_UElements&&, _Elements>...>::value;
+    }
+  };
+
+  template<typename... _Elements>
+  struct _TC<false, _Elements...>
+  {
+    template<typename... _UElements>
+    static constexpr bool _ConstructibleTuple()
+    {
+      return false;
+    }
+
+    template<typename... _UElements>
+    static constexpr bool _ImplicitlyConvertibleTuple()
+    {
+      return false;
+    }
+
+    template<typename... _UElements>
+    static constexpr bool _MoveConstructibleTuple()
+    {
+      return false;
+    }
+
+    template<typename... _UElements>
+    static constexpr bool _ImplicitlyMoveConvertibleTuple()
+    {
+      return false;
+    }
+  };
+
   /// Primary class template, tuple
   template<typename... _Elements> 
     class tuple : public _Tuple_impl<0, _Elements...>
     {
       typedef _Tuple_impl<0, _Elements...> _Inherited;
 
+      // Used for constraining the default constructor so
+      // that it becomes dependent on the constraints.
+      template<typename _Dummy>
+      struct _TC2
+      {
+        static constexpr bool _DefaultConstructibleTuple()
+        {
+          return __and_<is_default_constructible<_Elements>...>::value;
+        }
+      };
+
     public:
+      template<typename _Dummy = void,
+               typename enable_if<_TC2<_Dummy>::
+                                    _DefaultConstructibleTuple(),
+                                  bool>::type = true>
       constexpr tuple()
       : _Inherited() { }
 
-      explicit
-      constexpr tuple(const _Elements&... __elements)
+      // Shortcut for the cases where constructors taking _Elements...
+      // need to be constrained.
+      template<typename _Dummy> using _TCC =
+        _TC<is_same<_Dummy, void>::value,
+            _Elements...>;
+
+      template<typename _Dummy = void,
+               typename enable_if<
+                 _TCC<_Dummy>::template
+                   _ConstructibleTuple<_Elements...>()
+                 && _TCC<_Dummy>::template
+                   _ImplicitlyConvertibleTuple<_Elements...>()
+                 && (sizeof...(_Elements) >= 1),
+               bool>::type=true>
+        constexpr tuple(const _Elements&... __elements)
       : _Inherited(__elements...) { }
 
-      template<typename... _UElements, typename = typename
-        enable_if<__and_<is_convertible<_UElements,
-					_Elements>...>::value>::type>
-	explicit
+      template<typename _Dummy = void,
+               typename enable_if<
+                 _TCC<_Dummy>::template
+                   _ConstructibleTuple<_Elements...>()
+                 && !_TCC<_Dummy>::template
+                   _ImplicitlyConvertibleTuple<_Elements...>()
+                 && (sizeof...(_Elements) >= 1),
+               bool>::type=false>
+      explicit constexpr tuple(const _Elements&... __elements)
+      : _Inherited(__elements...) { }
+
+      // Shortcut for the cases where constructors taking _UElements...
+      // need to be constrained.
+      template<typename... _UElements> using _TMC =
+                  _TC<(sizeof...(_Elements) == sizeof...(_UElements)),
+                      _Elements...>;
+
+      template<typename... _UElements, typename
+        enable_if<_TMC<_UElements...>::template
+                    _MoveConstructibleTuple<_UElements...>()
+                  && _TMC<_UElements...>::template
+                    _ImplicitlyMoveConvertibleTuple<_UElements...>()
+                  && (sizeof...(_Elements) >= 1),
+        bool>::type=true>
         constexpr tuple(_UElements&&... __elements)
+        : _Inherited(std::forward<_UElements>(__elements)...) { }
+
+      template<typename... _UElements, typename
+        enable_if<_TMC<_UElements...>::template
+                    _MoveConstructibleTuple<_UElements...>()
+                  && !_TMC<_UElements...>::template
+                    _ImplicitlyMoveConvertibleTuple<_UElements...>()
+                  && (sizeof...(_Elements) >= 1),
+        bool>::type=false>
+        explicit constexpr tuple(_UElements&&... __elements)
 	: _Inherited(std::forward<_UElements>(__elements)...) {	}
 
       constexpr tuple(const tuple&) = default;
 
       constexpr tuple(tuple&&) = default; 
 
-      template<typename... _UElements, typename = typename
-        enable_if<__and_<is_convertible<const _UElements&,
-					_Elements>...>::value>::type>
+      template<typename... _UElements, typename
+        enable_if<_TMC<_UElements...>::template
+                    _ConstructibleTuple<_UElements...>()
+                  && _TMC<_UElements...>::template
+                    _ImplicitlyConvertibleTuple<_UElements...>(),
+        bool>::type=true>
         constexpr tuple(const tuple<_UElements...>& __in)
         : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
         { }
 
-      template<typename... _UElements, typename = typename
-        enable_if<__and_<is_convertible<_UElements,
-					_Elements>...>::value>::type>
+      template<typename... _UElements, typename
+        enable_if<_TMC<_UElements...>::template
+                    _ConstructibleTuple<_UElements...>()
+                  && !_TMC<_UElements...>::template
+                    _ImplicitlyConvertibleTuple<_UElements...>(),
+        bool>::type=false>
+        explicit constexpr tuple(const tuple<_UElements...>& __in)
+        : _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
+        { }
+
+      template<typename... _UElements, typename
+        enable_if<_TMC<_UElements...>::template
+                    _MoveConstructibleTuple<_UElements...>()
+                  && _TMC<_UElements...>::template
+                    _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+        bool>::type=true>
         constexpr tuple(tuple<_UElements...>&& __in)
         : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
 
+      template<typename... _UElements, typename
+        enable_if<_TMC<_UElements...>::template
+                    _MoveConstructibleTuple<_UElements...>()
+                  && !_TMC<_UElements...>::template
+                    _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+        bool>::type=false>
+        explicit constexpr tuple(tuple<_UElements...>&& __in)
+        : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
+
       // Allocator-extended constructors.
 
       template<typename _Alloc>
 	tuple(allocator_arg_t __tag, const _Alloc& __a)
 	: _Inherited(__tag, __a) { }
 
-      template<typename _Alloc>
+      template<typename _Alloc, typename _Dummy = void,
+               typename enable_if<
+                 _TCC<_Dummy>::template
+                   _ConstructibleTuple<_Elements...>()
+                 && _TCC<_Dummy>::template
+                   _ImplicitlyConvertibleTuple<_Elements...>(),
+               bool>::type=true>
 	tuple(allocator_arg_t __tag, const _Alloc& __a,
 	      const _Elements&... __elements)
 	: _Inherited(__tag, __a, __elements...) { }
 
-      template<typename _Alloc, typename... _UElements, typename = typename
-	       enable_if<sizeof...(_UElements)
-			 == sizeof...(_Elements)>::type>
+      template<typename _Alloc, typename _Dummy = void,
+               typename enable_if<
+                 _TCC<_Dummy>::template
+                   _ConstructibleTuple<_Elements...>()
+                 && !_TCC<_Dummy>::template
+                   _ImplicitlyConvertibleTuple<_Elements...>(),
+               bool>::type=false>
+	explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+                       const _Elements&... __elements)
+	: _Inherited(__tag, __a, __elements...) { }
+
+      template<typename _Alloc, typename... _UElements, typename
+        enable_if<_TMC<_UElements...>::template
+                    _MoveConstructibleTuple<_UElements...>()
+                  && _TMC<_UElements...>::template
+                    _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+        bool>::type=true>
 	tuple(allocator_arg_t __tag, const _Alloc& __a,
 	      _UElements&&... __elements)
 	: _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
        	{ }
 
+      template<typename _Alloc, typename... _UElements, typename
+        enable_if<_TMC<_UElements...>::template
+                    _MoveConstructibleTuple<_UElements...>()
+                  && !_TMC<_UElements...>::template
+                    _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+        bool>::type=false>
+	explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+	      _UElements&&... __elements)
+	: _Inherited(__tag, __a, std::forward<_UElements>(__elements)...)
+        { }
+
       template<typename _Alloc>
 	tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
 	: _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
@@ -522,24 +695,54 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
 	: _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
 
-      template<typename _Alloc, typename... _UElements, typename = typename
-	       enable_if<sizeof...(_UElements)
-			 == sizeof...(_Elements)>::type>
+      template<typename _Alloc, typename... _UElements, typename
+        enable_if<_TMC<_UElements...>::template
+                    _ConstructibleTuple<_UElements...>()
+                  && _TMC<_UElements...>::template
+                    _ImplicitlyConvertibleTuple<_UElements...>(),
+        bool>::type=true>
 	tuple(allocator_arg_t __tag, const _Alloc& __a,
 	      const tuple<_UElements...>& __in)
 	: _Inherited(__tag, __a,
 	             static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
 	{ }
 
-      template<typename _Alloc, typename... _UElements, typename = typename
-	       enable_if<sizeof...(_UElements)
-			 == sizeof...(_Elements)>::type>
+      template<typename _Alloc, typename... _UElements, typename
+        enable_if<_TMC<_UElements...>::template
+                    _ConstructibleTuple<_UElements...>()
+                  && !_TMC<_UElements...>::template
+                    _ImplicitlyConvertibleTuple<_UElements...>(),
+        bool>::type=false>
+	explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+	      const tuple<_UElements...>& __in)
+	: _Inherited(__tag, __a,
+	             static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
+	{ }
+
+      template<typename _Alloc, typename... _UElements, typename
+        enable_if<_TMC<_UElements...>::template
+                    _MoveConstructibleTuple<_UElements...>()
+                  && _TMC<_UElements...>::template
+                    _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+        bool>::type=true>
 	tuple(allocator_arg_t __tag, const _Alloc& __a,
 	      tuple<_UElements...>&& __in)
 	: _Inherited(__tag, __a,
 	             static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
 	{ }
 
+      template<typename _Alloc, typename... _UElements, typename
+        enable_if<_TMC<_UElements...>::template
+                    _MoveConstructibleTuple<_UElements...>()
+                  && !_TMC<_UElements...>::template
+                    _ImplicitlyMoveConvertibleTuple<_UElements...>(),
+        bool>::type=false>
+	explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+	      tuple<_UElements...>&& __in)
+	: _Inherited(__tag, __a,
+	             static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
+	{ }
+
       tuple&
       operator=(const tuple& __in)
       {
@@ -582,7 +785,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     };
 
   // Explicit specialization, zero-element tuple.
-  template<>  
+  template<>
     class tuple<>
     {
     public:
@@ -597,65 +800,190 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       typedef _Tuple_impl<0, _T1, _T2> _Inherited;
 
     public:
+      template <typename _U1 = _T1,
+                typename _U2 = _T2,
+                typename enable_if<__and_<
+                                     is_default_constructible<_U1>,
+                                     is_default_constructible<_U2>>
+                                   ::value, bool>::type = true>
+
       constexpr tuple()
       : _Inherited() { }
 
-      explicit
-      constexpr tuple(const _T1& __a1, const _T2& __a2)
-      : _Inherited(__a1, __a2) { }
-
-      template<typename _U1, typename _U2, typename = typename
-	       enable_if<__and_<is_convertible<_U1, _T1>,
-				is_convertible<_U2, _T2>>::value>::type>
-        explicit
+      // Shortcut for the cases where constructors taking _T1, _T2
+      // need to be constrained.
+      template<typename _Dummy> using _TCC =
+        _TC<is_same<_Dummy, void>::value, _T1, _T2>;
+
+      template<typename _Dummy = void, typename
+               enable_if<_TCC<_Dummy>::template
+                           _ConstructibleTuple<_T1, _T2>()
+                         && _TCC<_Dummy>::template
+                           _ImplicitlyConvertibleTuple<_T1, _T2>(),
+	bool>::type = true>
+        constexpr tuple(const _T1& __a1, const _T2& __a2)
+        : _Inherited(__a1, __a2) { }
+
+      template<typename _Dummy = void, typename
+               enable_if<_TCC<_Dummy>::template
+                           _ConstructibleTuple<_T1, _T2>()
+                         && !_TCC<_Dummy>::template
+                           _ImplicitlyConvertibleTuple<_T1, _T2>(),
+	bool>::type = false>
+        explicit constexpr tuple(const _T1& __a1, const _T2& __a2)
+        : _Inherited(__a1, __a2) { }
+
+      // Shortcut for the cases where constructors taking _U1, _U2
+      // need to be constrained.
+      using _TMC = _TC<true, _T1, _T2>;
+
+      template<typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _MoveConstructibleTuple<_U1, _U2>()
+                  && _TMC::template
+                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+	bool>::type = true>
         constexpr tuple(_U1&& __a1, _U2&& __a2)
 	: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
 
+      template<typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _MoveConstructibleTuple<_U1, _U2>()
+                  && !_TMC::template
+                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+	bool>::type = false>
+        explicit constexpr tuple(_U1&& __a1, _U2&& __a2)
+	: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
+
       constexpr tuple(const tuple&) = default;
 
       constexpr tuple(tuple&&) = default;
 
-      template<typename _U1, typename _U2, typename = typename
-	enable_if<__and_<is_convertible<const _U1&, _T1>,
-			 is_convertible<const _U2&, _T2>>::value>::type>
+      template<typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _ConstructibleTuple<_U1, _U2>()
+                  && _TMC::template
+                    _ImplicitlyConvertibleTuple<_U1, _U2>(),
+	bool>::type = true>
         constexpr tuple(const tuple<_U1, _U2>& __in)
 	: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
 
-      template<typename _U1, typename _U2, typename = typename
-	       enable_if<__and_<is_convertible<_U1, _T1>,
-				is_convertible<_U2, _T2>>::value>::type>
+      template<typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _ConstructibleTuple<_U1, _U2>()
+                  && !_TMC::template
+                    _ImplicitlyConvertibleTuple<_U1, _U2>(),
+	bool>::type = false>
+        explicit constexpr tuple(const tuple<_U1, _U2>& __in)
+	: _Inherited(static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in)) { }
+
+      template<typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _MoveConstructibleTuple<_U1, _U2>()
+                  && _TMC::template
+                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+	bool>::type = true>
         constexpr tuple(tuple<_U1, _U2>&& __in)
 	: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
 
-      template<typename _U1, typename _U2, typename = typename
-	enable_if<__and_<is_convertible<const _U1&, _T1>,
-			 is_convertible<const _U2&, _T2>>::value>::type>
+      template<typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _MoveConstructibleTuple<_U1, _U2>()
+                  && !_TMC::template
+                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+	bool>::type = false>
+        explicit constexpr tuple(tuple<_U1, _U2>&& __in)
+	: _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { }
+
+      template<typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _ConstructibleTuple<_U1, _U2>()
+                  && _TMC::template
+                    _ImplicitlyConvertibleTuple<_U1, _U2>(),
+	bool>::type = true>
         constexpr tuple(const pair<_U1, _U2>& __in)
 	: _Inherited(__in.first, __in.second) { }
 
-      template<typename _U1, typename _U2, typename = typename
-	       enable_if<__and_<is_convertible<_U1, _T1>,
-				is_convertible<_U2, _T2>>::value>::type>
+      template<typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _ConstructibleTuple<_U1, _U2>()
+                  && !_TMC::template
+                    _ImplicitlyConvertibleTuple<_U1, _U2>(),
+	bool>::type = false>
+        explicit constexpr tuple(const pair<_U1, _U2>& __in)
+	: _Inherited(__in.first, __in.second) { }
+
+      template<typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _MoveConstructibleTuple<_U1, _U2>()
+                  && _TMC::template
+                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+	bool>::type = true>
         constexpr tuple(pair<_U1, _U2>&& __in)
 	: _Inherited(std::forward<_U1>(__in.first),
 		     std::forward<_U2>(__in.second)) { }
 
+      template<typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _MoveConstructibleTuple<_U1, _U2>()
+                  && !_TMC::template
+                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+	bool>::type = false>
+        explicit constexpr tuple(pair<_U1, _U2>&& __in)
+	: _Inherited(std::forward<_U1>(__in.first),
+		     std::forward<_U2>(__in.second)) { }
+
       // Allocator-extended constructors.
 
       template<typename _Alloc>
 	tuple(allocator_arg_t __tag, const _Alloc& __a)
 	: _Inherited(__tag, __a) { }
 
-      template<typename _Alloc>
+      template<typename _Alloc, typename _Dummy = void,
+               typename enable_if<
+                 _TCC<_Dummy>::template
+                   _ConstructibleTuple<_T1, _T2>()
+                 && _TCC<_Dummy>::template
+                   _ImplicitlyConvertibleTuple<_T1, _T2>(),
+               bool>::type=true>
+
 	tuple(allocator_arg_t __tag, const _Alloc& __a,
 	      const _T1& __a1, const _T2& __a2)
 	: _Inherited(__tag, __a, __a1, __a2) { }
 
-      template<typename _Alloc, typename _U1, typename _U2>
+      template<typename _Alloc, typename _Dummy = void,
+               typename enable_if<
+                 _TCC<_Dummy>::template
+                   _ConstructibleTuple<_T1, _T2>()
+                 && !_TCC<_Dummy>::template
+                   _ImplicitlyConvertibleTuple<_T1, _T2>(),
+               bool>::type=false>
+
+	explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+	      const _T1& __a1, const _T2& __a2)
+	: _Inherited(__tag, __a, __a1, __a2) { }
+
+      template<typename _Alloc, typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _MoveConstructibleTuple<_U1, _U2>()
+                  && _TMC::template
+                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+	bool>::type = true>
 	tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2)
 	: _Inherited(__tag, __a, std::forward<_U1>(__a1),
 	             std::forward<_U2>(__a2)) { }
 
+      template<typename _Alloc, typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _MoveConstructibleTuple<_U1, _U2>()
+                  && !_TMC::template
+                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+	bool>::type = false>
+	explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+                       _U1&& __a1, _U2&& __a2)
+	: _Inherited(__tag, __a, std::forward<_U1>(__a1),
+	             std::forward<_U2>(__a2)) { }
+
       template<typename _Alloc>
 	tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in)
 	: _Inherited(__tag, __a, static_cast<const _Inherited&>(__in)) { }
@@ -664,28 +992,92 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in)
 	: _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { }
 
-      template<typename _Alloc, typename _U1, typename _U2>
+      template<typename _Alloc, typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _ConstructibleTuple<_U1, _U2>()
+                  && _TMC::template
+                    _ImplicitlyConvertibleTuple<_U1, _U2>(),
+	bool>::type = true>
 	tuple(allocator_arg_t __tag, const _Alloc& __a,
 	      const tuple<_U1, _U2>& __in)
 	: _Inherited(__tag, __a,
 	             static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
 	{ }
 
-      template<typename _Alloc, typename _U1, typename _U2>
+      template<typename _Alloc, typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _ConstructibleTuple<_U1, _U2>()
+                  && !_TMC::template
+                    _ImplicitlyConvertibleTuple<_U1, _U2>(),
+	bool>::type = false>
+	explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+	      const tuple<_U1, _U2>& __in)
+	: _Inherited(__tag, __a,
+	             static_cast<const _Tuple_impl<0, _U1, _U2>&>(__in))
+	{ }
+
+      template<typename _Alloc, typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _MoveConstructibleTuple<_U1, _U2>()
+                  && _TMC::template
+                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+	bool>::type = true>
 	tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in)
 	: _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
 	{ }
 
-      template<typename _Alloc, typename _U1, typename _U2>
+      template<typename _Alloc, typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _MoveConstructibleTuple<_U1, _U2>()
+                  && !_TMC::template
+                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+	bool>::type = false>
+	explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+                       tuple<_U1, _U2>&& __in)
+	: _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in))
+	{ }
+
+      template<typename _Alloc, typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _ConstructibleTuple<_U1, _U2>()
+                  && _TMC::template
+                    _ImplicitlyConvertibleTuple<_U1, _U2>(),
+	bool>::type = true>
         tuple(allocator_arg_t __tag, const _Alloc& __a,
 	      const pair<_U1, _U2>& __in)
 	: _Inherited(__tag, __a, __in.first, __in.second) { }
 
-      template<typename _Alloc, typename _U1, typename _U2>
+      template<typename _Alloc, typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _ConstructibleTuple<_U1, _U2>()
+                  && !_TMC::template
+                    _ImplicitlyConvertibleTuple<_U1, _U2>(),
+	bool>::type = false>
+        explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+	      const pair<_U1, _U2>& __in)
+	: _Inherited(__tag, __a, __in.first, __in.second) { }
+
+      template<typename _Alloc, typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _MoveConstructibleTuple<_U1, _U2>()
+                  && _TMC::template
+                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+	bool>::type = true>
         tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in)
 	: _Inherited(__tag, __a, std::forward<_U1>(__in.first),
 		     std::forward<_U2>(__in.second)) { }
 
+      template<typename _Alloc, typename _U1, typename _U2, typename
+        enable_if<_TMC::template
+                    _MoveConstructibleTuple<_U1, _U2>()
+                  && !_TMC::template
+                    _ImplicitlyMoveConvertibleTuple<_U1, _U2>(),
+	bool>::type = false>
+        explicit tuple(allocator_arg_t __tag, const _Alloc& __a,
+                       pair<_U1, _U2>&& __in)
+	: _Inherited(__tag, __a, std::forward<_U1>(__in.first),
+		     std::forward<_U2>(__in.second)) { }
+
       tuple&
       operator=(const tuple& __in)
       {
diff --git a/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc b/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
new file mode 100644
index 0000000..50edda9
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc
@@ -0,0 +1,108 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <utility>
+
+struct Explicit
+{
+  Explicit() = default;
+  explicit Explicit(int) {}
+};
+
+std::pair<int, int> f1() {return {1,2};}
+
+std::pair<Explicit, Explicit> f2() {return {1,2};} // { dg-error "explicit" }
+
+std::pair<long, long> f3() {return std::pair<int, int>{1,2};}
+
+std::pair<Explicit, Explicit> f4()
+{
+  return std::pair<int, int>{1,2};  // { dg-error "could not convert" }
+}
+
+std::pair<long, long> f5() {return {1,2};}
+
+std::pair<int, int> v0{1,2};
+
+std::pair<Explicit, Explicit> v1{1,2};
+
+std::pair<Explicit, Explicit> v2 = {1,2}; // { dg-error "explicit" }
+
+std::pair<Explicit, Explicit> v3{std::pair<int,int>{1,2}};
+
+std::pair<Explicit, Explicit> v4 =
+  std::pair<int,int>{1,2}; // { dg-error "conversion" }
+
+std::pair<char *, char *> v5(0,0);
+
+std::pair<long, long> v6{1,2};
+
+std::pair<long, long> v7 = {1,2};
+
+std::pair<long, long> v8{std::pair<int,int>{1,2}};
+
+std::pair<long, long> v9 = std::pair<int,int>{1,2};
+
+std::pair<Explicit, Explicit> v10{v0};
+
+std::pair<Explicit, Explicit> v11 = v0; // { dg-error "conversion" }
+
+std::pair<long, long> v12{v0};
+
+std::pair<long, long> v13 = v0;
+
+void f6(std::pair<Explicit, Explicit>) {}
+
+void f7(std::pair<long, long>) {}
+
+void test_arg_passing()
+{
+  f6(v0); // { dg-error "could not convert" }
+  f6(v1);
+  f6({1,2}); // { dg-error "explicit" }
+  f6(std::pair<Explicit, Explicit>{});
+  f6(std::pair<int, int>{}); // { dg-error "could not convert" }
+  f7(v0);
+  f7(v6);
+  f7({1,2});
+  f7(std::pair<int, int>{});
+  f7(std::pair<long, long>{});
+}
+
+struct MoveOnly
+{
+  MoveOnly() = default;
+  MoveOnly(MoveOnly&&) {}
+};
+
+struct ExplicitMoveOnly
+{
+  ExplicitMoveOnly() = default;
+  ExplicitMoveOnly(ExplicitMoveOnly&&) {}
+  explicit ExplicitMoveOnly(MoveOnly&&) {}
+};
+
+std::pair<int*, ExplicitMoveOnly> v14{0, MoveOnly{}};
+std::pair<ExplicitMoveOnly, int*> v15{MoveOnly{}, 0};
+
+std::pair<int*, ExplicitMoveOnly> v16 =
+  {0, MoveOnly{}}; // { dg-error "explicit" }
+std::pair<ExplicitMoveOnly, int*> v17 =
+  {MoveOnly{}, 0}; // { dg-error "explicit" }
diff --git a/libstdc++-v3/testsuite/20_util/pair/piecewise.cc b/libstdc++-v3/testsuite/20_util/pair/piecewise.cc
index bcdab7d..40ab16b 100644
--- a/libstdc++-v3/testsuite/20_util/pair/piecewise.cc
+++ b/libstdc++-v3/testsuite/20_util/pair/piecewise.cc
@@ -69,20 +69,20 @@ void test01()
 {
   bool test __attribute__((unused)) = true;
 
-  std::pair<type_one, type_zero> pp0(std::piecewise_construct_t(),
+  std::pair<type_one, type_zero> pp0(std::piecewise_construct,
 				     std::forward_as_tuple(-3),
 				     std::forward_as_tuple());
   VERIFY( pp0.first.get() == -3 );
   VERIFY( pp0.second.get() == 757 );
 
-  std::pair<type_one, type_two> pp1(std::piecewise_construct_t(),
+  std::pair<type_one, type_two> pp1(std::piecewise_construct,
 				    std::forward_as_tuple(6),
 				    std::forward_as_tuple(5, 4));
   VERIFY( pp1.first.get() == 6 );
   VERIFY( pp1.second.get1() == 5 );
   VERIFY( pp1.second.get2() == 4 );
 
-  std::pair<type_two, type_two> pp2(std::piecewise_construct_t(),
+  std::pair<type_two, type_two> pp2(std::piecewise_construct,
 				    std::forward_as_tuple(2, 1),
 				    std::forward_as_tuple(-1, -3));
   VERIFY( pp2.first.get1() == 2 );
diff --git a/libstdc++-v3/testsuite/20_util/pair/requirements/dr2367.cc b/libstdc++-v3/testsuite/20_util/pair/requirements/dr2367.cc
new file mode 100644
index 0000000..603b7c5
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/pair/requirements/dr2367.cc
@@ -0,0 +1,41 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <utility>
+#include <type_traits>
+
+// DR 2367, pair and tuple are not correctly implemented for is_constructible with no args
+void test_default_constructible()
+{
+  struct X
+  {
+    X() = delete;
+  };
+
+  typedef std::pair<int, X> P;
+  static_assert(!std::is_constructible<P>::value, "");
+  static_assert(!std::is_default_constructible<P>::value, "");
+}
+
+int main()
+{
+  test_default_constructible();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc b/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
new file mode 100644
index 0000000..114a490
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc
@@ -0,0 +1,282 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tuple>
+#include <utility>
+#include <memory>
+
+struct Explicit
+{
+  Explicit() = default;
+  explicit Explicit(int) {}
+};
+
+std::tuple<int> f1a() {return {1};}
+std::tuple<int, int> f1b() {return {1,2};}
+std::tuple<int, int, int> f1c() {return {1,2,3};}
+
+std::tuple<Explicit> f2_a() {return {1};} // { dg-error "explicit" }
+std::tuple<Explicit, Explicit> f2_b() {return {1,2};} // { dg-error "explicit" }
+std::tuple<Explicit, Explicit, Explicit> f2_c() {return {1,2,3};} // { dg-error "explicit" }
+
+std::tuple<long> f3_a() {return std::tuple<int>{1};}
+std::tuple<long, long> f3_b() {return std::tuple<int, int>{1,2};}
+std::tuple<long, long, long> f3_c() {return std::tuple<int, int, int>{1,2,3};}
+
+std::tuple<Explicit> f4_a()
+{
+  return std::tuple<int>{1};  // { dg-error "could not convert" }
+}
+std::tuple<Explicit, Explicit> f4_b()
+{
+  return std::tuple<int, int>{1,2};  // { dg-error "could not convert" }
+}
+std::tuple<Explicit, Explicit, Explicit> f4_c()
+{
+  return std::tuple<int, int,int>{1,2,3};  // { dg-error "could not convert" }
+}
+
+std::tuple<long> f5_a() {return {1};}
+std::tuple<long, long> f5_b() {return {1,2};}
+std::tuple<long, long, long> f5_c() {return {1,2,3};}
+
+std::tuple<int, int> fp1() {return std::pair<int, int>{1,2}; }
+std::tuple<long, long> fp2() {return std::pair<int, int>{1,2}; }
+std::tuple<Explicit, Explicit> fp3()
+  {return std::pair<int, int>{1,2}; } // { dg-error "could not convert" }
+
+std::tuple<int> v0_a{1};
+std::tuple<int, int> v0_b{1,2};
+std::tuple<int, int, int> v0_c{1,2,3};
+
+std::tuple<Explicit> v1_a{1};
+std::tuple<Explicit, Explicit> v1_b{1,2};
+std::tuple<Explicit, Explicit, Explicit> v1_c{1,2,3};
+
+std::tuple<Explicit> v2_a = {1}; // { dg-error "explicit" }
+std::tuple<Explicit, Explicit> v2_b = {1,2}; // { dg-error "explicit" }
+std::tuple<Explicit, Explicit, Explicit> v2_c = {1,2,3}; // { dg-error "explicit" }
+
+std::tuple<Explicit> v3_a{std::tuple<int>{1}};
+std::tuple<Explicit, Explicit> v3_b{std::tuple<int,int>{1,2}};
+std::tuple<Explicit, Explicit, Explicit> v3_c{std::tuple<int,int,int>{1,2,3}};
+
+std::tuple<Explicit, Explicit> v4_a =
+  std::tuple<int>{1}; // { dg-error "conversion" }
+std::tuple<Explicit, Explicit> v4_b =
+  std::tuple<int,int>{1,2}; // { dg-error "conversion" }
+std::tuple<Explicit, Explicit, Explicit> v4_c =
+  std::tuple<int,int,int>{1,2,3}; // { dg-error "conversion" }
+
+std::tuple<long> v6_a{1};
+std::tuple<long, long> v6_b{1,2};
+std::tuple<long, long, long> v6_c{1,2,3};
+
+std::tuple<long> v7_a = {1};
+std::tuple<long, long> v7_b = {1,2};
+std::tuple<long, long, long> v7_c = {1,2,3};
+
+std::tuple<long> v8_a{std::tuple<int>{1}};
+std::tuple<long, long> v8_b{std::tuple<int,int>{1,2}};
+std::tuple<long, long, long> v8_c{std::tuple<int,int,int>{1,2,3}};
+
+std::tuple<long> v9_a = std::tuple<int>{1};
+std::tuple<long, long> v9_b = std::tuple<int,int>{1,2};
+std::tuple<long, long, long> v9_c = std::tuple<int,int,int>{1,2,3};
+
+std::tuple<Explicit> v10_a{v0_a};
+std::tuple<Explicit, Explicit> v10_b{v0_b};
+std::tuple<Explicit, Explicit, Explicit> v10_c{v0_c};
+
+std::tuple<Explicit> v11_a = v0_a; // { dg-error "conversion" }
+std::tuple<Explicit, Explicit> v11_b = v0_b; // { dg-error "conversion" }
+std::tuple<Explicit, Explicit, Explicit> v11_c
+  = v0_c; // { dg-error "conversion" }
+
+std::tuple<long> v12_a{v0_a};
+std::tuple<long, long> v12_b{v0_b};
+std::tuple<long, long, long> v12_c{v0_c};
+
+std::tuple<long> v13_a = v0_a;
+std::tuple<long, long> v13_b = v0_b;
+std::tuple<long, long, long> v13_c = v0_c;
+
+std::tuple<int, int> v14{std::pair<int, int>{1,2}};
+std::tuple<long, long> v15{std::pair<int, int>{1,2}};
+std::tuple<Explicit, Explicit> v16{std::pair<int, int>{1,2}};
+
+std::tuple<int, int> v17 = std::pair<int, int>{1,2};
+std::tuple<long, long> v18 = std::pair<int, int>{1,2};
+std::tuple<Explicit, Explicit> v19
+  = std::pair<int, int>{1,2}; // { dg-error "conversion" }
+
+std::pair<int, int> v20;
+
+std::tuple<int, int> v21{v20};
+std::tuple<long, long> v22{v20};
+std::tuple<Explicit, Explicit> v23{v20};
+
+std::tuple<int, int> v24 = v20;
+std::tuple<long, long> v25 = v20;
+std::tuple<Explicit, Explicit> v26 = v20; // { dg-error "conversion" }
+
+std::tuple<int> v27_a{std::allocator_arg, std::allocator<int>{}, 1};
+std::tuple<int, int> v27_b{std::allocator_arg, std::allocator<int>{}, 1, 2};
+std::tuple<int, int, int> v27_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
+
+std::tuple<long> v28_a{std::allocator_arg, std::allocator<int>{}, 1};
+std::tuple<long, long> v28_b{std::allocator_arg, std::allocator<int>{}, 1, 2};
+std::tuple<long, long, long>
+  v28_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
+
+std::tuple<Explicit> v29_a{std::allocator_arg, std::allocator<int>{}, 1};
+std::tuple<Explicit, Explicit>
+  v29_b{std::allocator_arg, std::allocator<int>{}, 1, 2};
+std::tuple<Explicit, Explicit, Explicit>
+  v29_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
+
+std::tuple<int> v30_a = {std::allocator_arg, std::allocator<int>{}, 1};
+std::tuple<int, int> v30_b = {std::allocator_arg, std::allocator<int>{}, 1, 2};
+std::tuple<int, int, int> v30_c
+  = {std::allocator_arg, std::allocator<int>{}, 1,2,3};
+
+std::tuple<long> v31_a = {std::allocator_arg, std::allocator<int>{}, 1};
+std::tuple<long, long> v31_b = {std::allocator_arg, std::allocator<int>{}, 1, 2};
+std::tuple<long, long, long>
+  v31_c{std::allocator_arg, std::allocator<int>{}, 1,2,3};
+
+std::tuple<Explicit> v32_a
+  = {std::allocator_arg, std::allocator<int>{}, 1}; // { dg-error "explicit" }
+std::tuple<Explicit, Explicit> v32_b
+  = {std::allocator_arg, std::allocator<int>{}, 1, 2}; // { dg-error "explicit" }
+std::tuple<Explicit, Explicit, Explicit> v32_c
+  = {std::allocator_arg, std::allocator<int>{}, 1,2,3}; // { dg-error "explicit" }
+
+std::tuple<int, int> v33{std::allocator_arg, std::allocator<int>{},
+  std::pair<int, int>{1, 2}};
+
+std::tuple<long, long> v34{std::allocator_arg, std::allocator<int>{},
+  std::pair<int, int>{1, 2}};
+
+std::tuple<Explicit, Explicit>
+  v35{std::allocator_arg, std::allocator<int>{}, std::pair<int, int>{1, 2}};
+
+std::tuple<int, int> v36 = {std::allocator_arg, std::allocator<int>{},
+  std::pair<int, int>{1, 2}};
+
+std::tuple<long, long> v37 = {std::allocator_arg, std::allocator<int>{},
+  std::pair<int, int>{1, 2}};
+
+std::tuple<Explicit, Explicit> v38
+= {std::allocator_arg, std::allocator<int>{}, std::pair<int, int>{1, 2}}; // { dg-error "explicit" }
+
+std::tuple<int, int> v39{std::allocator_arg, std::allocator<int>{}, v20};
+
+std::tuple<long, long> v40{std::allocator_arg, std::allocator<int>{}, v20};
+
+std::tuple<Explicit, Explicit>
+  v41{std::allocator_arg, std::allocator<int>{}, v20};
+
+std::tuple<int, int> v42 = {std::allocator_arg, std::allocator<int>{}, v20};
+
+std::tuple<long, long> v43 = {std::allocator_arg, std::allocator<int>{}, v20};
+
+std::tuple<Explicit, Explicit> v44
+= {std::allocator_arg, std::allocator<int>{}, v20}; // { dg-error "explicit" }
+
+struct DeletedCopy
+{
+  DeletedCopy(int);
+  DeletedCopy(const DeletedCopy&) = delete;
+};
+
+std::tuple<DeletedCopy> v45{42};
+std::tuple<DeletedCopy> v46{std::allocator_arg,
+    std::allocator<DeletedCopy>{}, 42};
+
+struct Sanity
+{
+  int v;
+};
+
+std::tuple<int, Sanity> v47(3, {42});
+std::tuple<int, int, Sanity> v48(3, 4, {42});
+std::tuple<int, Sanity> v49(std::allocator_arg,
+                            std::allocator<Sanity>{},
+                            3, {42});
+std::tuple<int, int, Sanity> v50(std::allocator_arg,
+                                 std::allocator<Sanity>{},
+                                 3, 4, {42});
+
+void f6_a(std::tuple<Explicit>) {}
+void f6_b(std::tuple<Explicit, Explicit>) {}
+void f6_c(std::tuple<Explicit, Explicit, Explicit>) {}
+
+void f7_a(std::tuple<long>) {}
+void f7_b(std::tuple<long, long>) {}
+void f7_c(std::tuple<long, long, long>) {}
+
+void test_arg_passing()
+{
+  f6_a(v0_a); // { dg-error "could not convert" }
+  f6_b(v0_b); // { dg-error "could not convert" }
+  f6_c(v0_c); // { dg-error "could not convert" }
+  f6_b(v20); // { dg-error "could not convert" }
+
+  f6_a(v1_a);
+  f6_b(v1_b);
+  f6_c(v1_c);
+
+  f6_a({1}); // { dg-error "explicit" }
+  f6_b({1,2}); // { dg-error "explicit" }
+  f6_c({1,2,3}); // { dg-error "explicit" }
+
+  f6_a(std::tuple<Explicit>{});
+  f6_b(std::tuple<Explicit, Explicit>{});
+  f6_c(std::tuple<Explicit, Explicit, Explicit>{});
+
+  f6_a(std::tuple<int>{}); // { dg-error "could not convert" }
+  f6_b(std::tuple<int, int>{}); // { dg-error "could not convert" }
+  f6_c(std::tuple<int, int, int>{}); // { dg-error "could not convert" }
+  f6_b(std::pair<int, int>{}); // { dg-error "could not convert" }
+
+  f7_a(v0_a);
+  f7_b(v0_b);
+  f7_c(v0_c);
+  f7_b(v20);
+
+  f7_a(v6_a);
+  f7_b(v6_b);
+  f7_c(v6_c);
+
+  f7_a({1});
+  f7_b({1,2});
+  f7_c({1,2,3});
+
+  f7_a(std::tuple<int>{});
+  f7_b(std::tuple<int, int>{});
+  f7_c(std::tuple<int, int, int>{});
+  f7_b(std::pair<int, int>{});
+
+
+  f7_a(std::tuple<long>{});
+  f7_b(std::tuple<long, long>{});
+  f7_c(std::tuple<long, long, long>{});
+}
diff --git a/libstdc++-v3/testsuite/20_util/tuple/requirements/dr2367.cc b/libstdc++-v3/testsuite/20_util/tuple/requirements/dr2367.cc
new file mode 100644
index 0000000..d3b975b
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/tuple/requirements/dr2367.cc
@@ -0,0 +1,47 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++11" }
+
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <tuple>
+#include <type_traits>
+
+// DR 2367, pair and tuple are not correctly implemented for is_constructible with no args
+void test_default_constructible()
+{
+  struct X
+  {
+    X() = delete;
+  };
+
+  typedef std::tuple<int, X> T;
+  static_assert(!std::is_constructible<T>::value, "");
+  static_assert(!std::is_default_constructible<T>::value, "");
+
+  typedef std::tuple<int, int, X> T2;
+  static_assert(!std::is_constructible<T2>::value, "");
+  static_assert(!std::is_default_constructible<T2>::value, "");
+
+
+}
+
+int main()
+{
+  test_default_constructible();
+  return 0;
+}

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2015-06-30 13:27 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-07  6:53 [v3 PATCH] Implement N4387 and LWG 2367 Ville Voutilainen
2015-06-07  8:13 ` Marc Glisse
2015-06-07  8:33   ` Ville Voutilainen
2015-06-07  8:49     ` Ville Voutilainen
2015-06-07  8:50       ` Ville Voutilainen
2015-06-07 11:37       ` Marc Glisse
2015-06-08 15:41 ` Martin Sebor
2015-06-08 15:56   ` Ville Voutilainen
2015-06-08 16:16     ` Ville Voutilainen
2015-06-14  7:07       ` Ville Voutilainen
2015-06-30 13:28         ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).