This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [v3 PATCH] Implement N4387 and LWG 2367


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.

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;
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]