Implement N4387, "Improving pair and tuple", and LWG 2367.
authorVille Voutilainen <ville.voutilainen@gmail.com>
Tue, 30 Jun 2015 13:26:49 +0000 (16:26 +0300)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 30 Jun 2015 13:26:49 +0000 (14:26 +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.

From-SVN: r225189

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/stl_pair.h
libstdc++-v3/include/experimental/functional
libstdc++-v3/include/std/tuple
libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/pair/piecewise.cc
libstdc++-v3/testsuite/20_util/pair/requirements/dr2367.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/tuple/requirements/dr2367.cc [new file with mode: 0644]

index 0ad5607..3a3192f 100644 (file)
@@ -1,3 +1,34 @@
+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.
+
 2015-06-30  Jonathan Wakely  <jwakely@redhat.com>
 
        * configure: Regenerate.
index 490b005..6672ecb 100644 (file)
@@ -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...>);
 
index 0472f59..c6b9800 100644 (file)
@@ -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)
index 0504012..59b992a 100644 (file)
@@ -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 (file)
index 0000000..50edda9
--- /dev/null
@@ -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" }
index bcdab7d..40ab16b 100644 (file)
@@ -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 (file)
index 0000000..603b7c5
--- /dev/null
@@ -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 (file)
index 0000000..114a490
--- /dev/null
@@ -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 (file)
index 0000000..d3b975b
--- /dev/null
@@ -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;
+}