From bf7818bfb0c70e626f8b71501ada3263f306a476 Mon Sep 17 00:00:00 2001 From: Ville Voutilainen Date: Tue, 30 Jun 2015 16:26:49 +0300 Subject: [PATCH] Implement N4387, "Improving pair and tuple", and LWG 2367. 2015-06-30 Ville Voutilainen 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 | 31 ++ libstdc++-v3/include/bits/stl_pair.h | 158 +++++- libstdc++-v3/include/experimental/functional | 2 +- libstdc++-v3/include/std/tuple | 490 ++++++++++++++++-- .../20_util/pair/cons/explicit_construct.cc | 108 ++++ .../testsuite/20_util/pair/piecewise.cc | 6 +- .../20_util/pair/requirements/dr2367.cc | 41 ++ .../20_util/tuple/cons/explicit_construct.cc | 282 ++++++++++ .../20_util/tuple/requirements/dr2367.cc | 47 ++ 9 files changed, 1091 insertions(+), 74 deletions(-) create mode 100644 libstdc++-v3/testsuite/20_util/pair/cons/explicit_construct.cc create mode 100644 libstdc++-v3/testsuite/20_util/pair/requirements/dr2367.cc create mode 100644 libstdc++-v3/testsuite/20_util/tuple/cons/explicit_construct.cc create mode 100644 libstdc++-v3/testsuite/20_util/tuple/requirements/dr2367.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 0ad56076761..3a3192fabb6 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,34 @@ +2015-06-30 Ville Voutilainen + + 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 * configure: Regenerate. diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h index 490b00565a0..6672ecb2273 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 struct _Index_tuple; + + // Concept utility functions, reused in conditionally-explicit + // constructors. + template + constexpr bool _ConstructiblePair() + { + return __and_, + is_constructible<_T2, const _U2&>>::value; + } + + template + constexpr bool _ImplicitlyConvertiblePair() + { + return __and_, + is_convertible>::value; + } + + template + constexpr bool _MoveConstructiblePair() + { + return __and_, + is_constructible<_T2, _U2&&>>::value; + } + + template + constexpr bool _ImplicitlyMoveConvertiblePair() + { + return __and_, + 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 , + 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() + && _ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(), + bool>::type=true> + constexpr pair(const _T1& __a, const _T2& __b) : first(__a), second(__b) { } + template() + && !_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 pair(const pair<_U1, _U2>& __p) : first(__p.first), second(__p.second) { } #else - template, - is_convertible>::value>::type> - constexpr pair(const pair<_U1, _U2>& __p) + template() + && _ImplicitlyConvertiblePair<_T1, _T2, _U1, _U2>(), + bool>::type=true> + constexpr pair(const pair<_U1, _U2>& __p) + : first(__p.first), second(__p.second) { } + + template() + && !_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::value>::type> - constexpr pair(_U1&& __x, const _T2& __y) - : first(std::forward<_U1>(__x)), second(__y) { } - - template::value>::type> - constexpr pair(const _T1& __x, _U2&& __y) - : first(__x), second(std::forward<_U2>(__y)) { } - - template, - is_convertible<_U2, _T2>>::value>::type> + template() + && _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() + && _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() + && _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() + && _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() + && _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, - is_convertible<_U2, _T2>>::value>::type> + template() + && !_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() + && _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() + && !_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 pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>); diff --git a/libstdc++-v3/include/experimental/functional b/libstdc++-v3/include/experimental/functional index 0472f593df5..c6b9800f7a6 100644 --- a/libstdc++-v3/include/experimental/functional +++ b/libstdc++-v3/include/experimental/functional @@ -124,7 +124,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template __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 0504012cbd1..59b992a4a06 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 + struct _TC + { + template + static constexpr bool _ConstructibleTuple() + { + return __and_...>::value; + } + + template + static constexpr bool _ImplicitlyConvertibleTuple() + { + return __and_...>::value; + } + + template + static constexpr bool _MoveConstructibleTuple() + { + return __and_...>::value; + } + + template + static constexpr bool _ImplicitlyMoveConvertibleTuple() + { + return __and_...>::value; + } + }; + + template + struct _TC + { + template + static constexpr bool _ConstructibleTuple() + { + return false; + } + + template + static constexpr bool _ImplicitlyConvertibleTuple() + { + return false; + } + + template + static constexpr bool _MoveConstructibleTuple() + { + return false; + } + + template + static constexpr bool _ImplicitlyMoveConvertibleTuple() + { + return false; + } + }; + /// Primary class template, tuple template 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 + struct _TC2 + { + static constexpr bool _DefaultConstructibleTuple() + { + return __and_...>::value; + } + }; + public: + template:: + _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 using _TCC = + _TC::value, + _Elements...>; + + template::template + _ConstructibleTuple<_Elements...>() + && _TCC<_Dummy>::template + _ImplicitlyConvertibleTuple<_Elements...>() + && (sizeof...(_Elements) >= 1), + bool>::type=true> + constexpr tuple(const _Elements&... __elements) : _Inherited(__elements...) { } - template...>::value>::type> - explicit + template::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 using _TMC = + _TC<(sizeof...(_Elements) == sizeof...(_UElements)), + _Elements...>; + + template::template + _MoveConstructibleTuple<_UElements...>() + && _TMC<_UElements...>::template + _ImplicitlyMoveConvertibleTuple<_UElements...>() + && (sizeof...(_Elements) >= 1), + bool>::type=true> constexpr tuple(_UElements&&... __elements) + : _Inherited(std::forward<_UElements>(__elements)...) { } + + template::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...>::value>::type> + template::template + _ConstructibleTuple<_UElements...>() + && _TMC<_UElements...>::template + _ImplicitlyConvertibleTuple<_UElements...>(), + bool>::type=true> constexpr tuple(const tuple<_UElements...>& __in) : _Inherited(static_cast&>(__in)) { } - template...>::value>::type> + template::template + _ConstructibleTuple<_UElements...>() + && !_TMC<_UElements...>::template + _ImplicitlyConvertibleTuple<_UElements...>(), + bool>::type=false> + explicit constexpr tuple(const tuple<_UElements...>& __in) + : _Inherited(static_cast&>(__in)) + { } + + template::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::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 tuple(allocator_arg_t __tag, const _Alloc& __a) : _Inherited(__tag, __a) { } - template + template::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::type> + template::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::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::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 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) : _Inherited(__tag, __a, static_cast(__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::type> + template::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&>(__in)) { } - template::type> + template::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&>(__in)) + { } + + template::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::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 , + is_default_constructible<_U2>> + ::value, bool>::type = true> + constexpr tuple() : _Inherited() { } - explicit - constexpr tuple(const _T1& __a1, const _T2& __a2) - : _Inherited(__a1, __a2) { } - - template, - is_convertible<_U2, _T2>>::value>::type> - explicit + // Shortcut for the cases where constructors taking _T1, _T2 + // need to be constrained. + template using _TCC = + _TC::value, _T1, _T2>; + + template::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::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; + + template() + && _TMC::template + _ImplicitlyMoveConvertibleTuple<_U1, _U2>(), + bool>::type = true> constexpr tuple(_U1&& __a1, _U2&& __a2) : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { } + template() + && !_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, - is_convertible>::value>::type> + template() + && _TMC::template + _ImplicitlyConvertibleTuple<_U1, _U2>(), + bool>::type = true> constexpr tuple(const tuple<_U1, _U2>& __in) : _Inherited(static_cast&>(__in)) { } - template, - is_convertible<_U2, _T2>>::value>::type> + template() + && !_TMC::template + _ImplicitlyConvertibleTuple<_U1, _U2>(), + bool>::type = false> + explicit constexpr tuple(const tuple<_U1, _U2>& __in) + : _Inherited(static_cast&>(__in)) { } + + template() + && _TMC::template + _ImplicitlyMoveConvertibleTuple<_U1, _U2>(), + bool>::type = true> constexpr tuple(tuple<_U1, _U2>&& __in) : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { } - template, - is_convertible>::value>::type> + template() + && !_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() + && _TMC::template + _ImplicitlyConvertibleTuple<_U1, _U2>(), + bool>::type = true> constexpr tuple(const pair<_U1, _U2>& __in) : _Inherited(__in.first, __in.second) { } - template, - is_convertible<_U2, _T2>>::value>::type> + template() + && !_TMC::template + _ImplicitlyConvertibleTuple<_U1, _U2>(), + bool>::type = false> + explicit constexpr tuple(const pair<_U1, _U2>& __in) + : _Inherited(__in.first, __in.second) { } + + template() + && _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() + && !_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 tuple(allocator_arg_t __tag, const _Alloc& __a) : _Inherited(__tag, __a) { } - template + template::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 + template::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() + && _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() + && !_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 tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) : _Inherited(__tag, __a, static_cast(__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 + template() + && _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&>(__in)) { } - template + template() + && !_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&>(__in)) + { } + + template() + && _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 + template() + && !_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() + && _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 + template() + && !_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() + && _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() + && !_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 00000000000..50edda9151a --- /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 +// . + +#include + +struct Explicit +{ + Explicit() = default; + explicit Explicit(int) {} +}; + +std::pair f1() {return {1,2};} + +std::pair f2() {return {1,2};} // { dg-error "explicit" } + +std::pair f3() {return std::pair{1,2};} + +std::pair f4() +{ + return std::pair{1,2}; // { dg-error "could not convert" } +} + +std::pair f5() {return {1,2};} + +std::pair v0{1,2}; + +std::pair v1{1,2}; + +std::pair v2 = {1,2}; // { dg-error "explicit" } + +std::pair v3{std::pair{1,2}}; + +std::pair v4 = + std::pair{1,2}; // { dg-error "conversion" } + +std::pair v5(0,0); + +std::pair v6{1,2}; + +std::pair v7 = {1,2}; + +std::pair v8{std::pair{1,2}}; + +std::pair v9 = std::pair{1,2}; + +std::pair v10{v0}; + +std::pair v11 = v0; // { dg-error "conversion" } + +std::pair v12{v0}; + +std::pair v13 = v0; + +void f6(std::pair) {} + +void f7(std::pair) {} + +void test_arg_passing() +{ + f6(v0); // { dg-error "could not convert" } + f6(v1); + f6({1,2}); // { dg-error "explicit" } + f6(std::pair{}); + f6(std::pair{}); // { dg-error "could not convert" } + f7(v0); + f7(v6); + f7({1,2}); + f7(std::pair{}); + f7(std::pair{}); +} + +struct MoveOnly +{ + MoveOnly() = default; + MoveOnly(MoveOnly&&) {} +}; + +struct ExplicitMoveOnly +{ + ExplicitMoveOnly() = default; + ExplicitMoveOnly(ExplicitMoveOnly&&) {} + explicit ExplicitMoveOnly(MoveOnly&&) {} +}; + +std::pair v14{0, MoveOnly{}}; +std::pair v15{MoveOnly{}, 0}; + +std::pair v16 = + {0, MoveOnly{}}; // { dg-error "explicit" } +std::pair 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 bcdab7d60c7..40ab16b14b9 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 pp0(std::piecewise_construct_t(), + std::pair 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 pp1(std::piecewise_construct_t(), + std::pair 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 pp2(std::piecewise_construct_t(), + std::pair 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 00000000000..603b7c57074 --- /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 +// . + +#include +#include + +// 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 P; + static_assert(!std::is_constructible

::value, ""); + static_assert(!std::is_default_constructible

::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 00000000000..114a4906f1f --- /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 +// . + +#include +#include +#include + +struct Explicit +{ + Explicit() = default; + explicit Explicit(int) {} +}; + +std::tuple f1a() {return {1};} +std::tuple f1b() {return {1,2};} +std::tuple f1c() {return {1,2,3};} + +std::tuple f2_a() {return {1};} // { dg-error "explicit" } +std::tuple f2_b() {return {1,2};} // { dg-error "explicit" } +std::tuple f2_c() {return {1,2,3};} // { dg-error "explicit" } + +std::tuple f3_a() {return std::tuple{1};} +std::tuple f3_b() {return std::tuple{1,2};} +std::tuple f3_c() {return std::tuple{1,2,3};} + +std::tuple f4_a() +{ + return std::tuple{1}; // { dg-error "could not convert" } +} +std::tuple f4_b() +{ + return std::tuple{1,2}; // { dg-error "could not convert" } +} +std::tuple f4_c() +{ + return std::tuple{1,2,3}; // { dg-error "could not convert" } +} + +std::tuple f5_a() {return {1};} +std::tuple f5_b() {return {1,2};} +std::tuple f5_c() {return {1,2,3};} + +std::tuple fp1() {return std::pair{1,2}; } +std::tuple fp2() {return std::pair{1,2}; } +std::tuple fp3() + {return std::pair{1,2}; } // { dg-error "could not convert" } + +std::tuple v0_a{1}; +std::tuple v0_b{1,2}; +std::tuple v0_c{1,2,3}; + +std::tuple v1_a{1}; +std::tuple v1_b{1,2}; +std::tuple v1_c{1,2,3}; + +std::tuple v2_a = {1}; // { dg-error "explicit" } +std::tuple v2_b = {1,2}; // { dg-error "explicit" } +std::tuple v2_c = {1,2,3}; // { dg-error "explicit" } + +std::tuple v3_a{std::tuple{1}}; +std::tuple v3_b{std::tuple{1,2}}; +std::tuple v3_c{std::tuple{1,2,3}}; + +std::tuple v4_a = + std::tuple{1}; // { dg-error "conversion" } +std::tuple v4_b = + std::tuple{1,2}; // { dg-error "conversion" } +std::tuple v4_c = + std::tuple{1,2,3}; // { dg-error "conversion" } + +std::tuple v6_a{1}; +std::tuple v6_b{1,2}; +std::tuple v6_c{1,2,3}; + +std::tuple v7_a = {1}; +std::tuple v7_b = {1,2}; +std::tuple v7_c = {1,2,3}; + +std::tuple v8_a{std::tuple{1}}; +std::tuple v8_b{std::tuple{1,2}}; +std::tuple v8_c{std::tuple{1,2,3}}; + +std::tuple v9_a = std::tuple{1}; +std::tuple v9_b = std::tuple{1,2}; +std::tuple v9_c = std::tuple{1,2,3}; + +std::tuple v10_a{v0_a}; +std::tuple v10_b{v0_b}; +std::tuple v10_c{v0_c}; + +std::tuple v11_a = v0_a; // { dg-error "conversion" } +std::tuple v11_b = v0_b; // { dg-error "conversion" } +std::tuple v11_c + = v0_c; // { dg-error "conversion" } + +std::tuple v12_a{v0_a}; +std::tuple v12_b{v0_b}; +std::tuple v12_c{v0_c}; + +std::tuple v13_a = v0_a; +std::tuple v13_b = v0_b; +std::tuple v13_c = v0_c; + +std::tuple v14{std::pair{1,2}}; +std::tuple v15{std::pair{1,2}}; +std::tuple v16{std::pair{1,2}}; + +std::tuple v17 = std::pair{1,2}; +std::tuple v18 = std::pair{1,2}; +std::tuple v19 + = std::pair{1,2}; // { dg-error "conversion" } + +std::pair v20; + +std::tuple v21{v20}; +std::tuple v22{v20}; +std::tuple v23{v20}; + +std::tuple v24 = v20; +std::tuple v25 = v20; +std::tuple v26 = v20; // { dg-error "conversion" } + +std::tuple v27_a{std::allocator_arg, std::allocator{}, 1}; +std::tuple v27_b{std::allocator_arg, std::allocator{}, 1, 2}; +std::tuple v27_c{std::allocator_arg, std::allocator{}, 1,2,3}; + +std::tuple v28_a{std::allocator_arg, std::allocator{}, 1}; +std::tuple v28_b{std::allocator_arg, std::allocator{}, 1, 2}; +std::tuple + v28_c{std::allocator_arg, std::allocator{}, 1,2,3}; + +std::tuple v29_a{std::allocator_arg, std::allocator{}, 1}; +std::tuple + v29_b{std::allocator_arg, std::allocator{}, 1, 2}; +std::tuple + v29_c{std::allocator_arg, std::allocator{}, 1,2,3}; + +std::tuple v30_a = {std::allocator_arg, std::allocator{}, 1}; +std::tuple v30_b = {std::allocator_arg, std::allocator{}, 1, 2}; +std::tuple v30_c + = {std::allocator_arg, std::allocator{}, 1,2,3}; + +std::tuple v31_a = {std::allocator_arg, std::allocator{}, 1}; +std::tuple v31_b = {std::allocator_arg, std::allocator{}, 1, 2}; +std::tuple + v31_c{std::allocator_arg, std::allocator{}, 1,2,3}; + +std::tuple v32_a + = {std::allocator_arg, std::allocator{}, 1}; // { dg-error "explicit" } +std::tuple v32_b + = {std::allocator_arg, std::allocator{}, 1, 2}; // { dg-error "explicit" } +std::tuple v32_c + = {std::allocator_arg, std::allocator{}, 1,2,3}; // { dg-error "explicit" } + +std::tuple v33{std::allocator_arg, std::allocator{}, + std::pair{1, 2}}; + +std::tuple v34{std::allocator_arg, std::allocator{}, + std::pair{1, 2}}; + +std::tuple + v35{std::allocator_arg, std::allocator{}, std::pair{1, 2}}; + +std::tuple v36 = {std::allocator_arg, std::allocator{}, + std::pair{1, 2}}; + +std::tuple v37 = {std::allocator_arg, std::allocator{}, + std::pair{1, 2}}; + +std::tuple v38 += {std::allocator_arg, std::allocator{}, std::pair{1, 2}}; // { dg-error "explicit" } + +std::tuple v39{std::allocator_arg, std::allocator{}, v20}; + +std::tuple v40{std::allocator_arg, std::allocator{}, v20}; + +std::tuple + v41{std::allocator_arg, std::allocator{}, v20}; + +std::tuple v42 = {std::allocator_arg, std::allocator{}, v20}; + +std::tuple v43 = {std::allocator_arg, std::allocator{}, v20}; + +std::tuple v44 += {std::allocator_arg, std::allocator{}, v20}; // { dg-error "explicit" } + +struct DeletedCopy +{ + DeletedCopy(int); + DeletedCopy(const DeletedCopy&) = delete; +}; + +std::tuple v45{42}; +std::tuple v46{std::allocator_arg, + std::allocator{}, 42}; + +struct Sanity +{ + int v; +}; + +std::tuple v47(3, {42}); +std::tuple v48(3, 4, {42}); +std::tuple v49(std::allocator_arg, + std::allocator{}, + 3, {42}); +std::tuple v50(std::allocator_arg, + std::allocator{}, + 3, 4, {42}); + +void f6_a(std::tuple) {} +void f6_b(std::tuple) {} +void f6_c(std::tuple) {} + +void f7_a(std::tuple) {} +void f7_b(std::tuple) {} +void f7_c(std::tuple) {} + +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{}); + f6_b(std::tuple{}); + f6_c(std::tuple{}); + + f6_a(std::tuple{}); // { dg-error "could not convert" } + f6_b(std::tuple{}); // { dg-error "could not convert" } + f6_c(std::tuple{}); // { dg-error "could not convert" } + f6_b(std::pair{}); // { 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{}); + f7_b(std::tuple{}); + f7_c(std::tuple{}); + f7_b(std::pair{}); + + + f7_a(std::tuple{}); + f7_b(std::tuple{}); + f7_c(std::tuple{}); +} 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 00000000000..d3b975bd0f1 --- /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 +// . + +#include +#include + +// 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 T; + static_assert(!std::is_constructible::value, ""); + static_assert(!std::is_default_constructible::value, ""); + + typedef std::tuple T2; + static_assert(!std::is_constructible::value, ""); + static_assert(!std::is_default_constructible::value, ""); + + +} + +int main() +{ + test_default_constructible(); + return 0; +} -- 2.30.2