Index: include/tuple =================================================================== --- include/tuple +++ include/tuple @@ -184,7 +184,6 @@ { _Hp value; - __tuple_leaf& operator=(const __tuple_leaf&); public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __tuple_leaf() _NOEXCEPT_(is_nothrow_default_constructible<_Hp>::value) : value() @@ -215,7 +214,9 @@ template ::type, __tuple_leaf>> + __lazy_not>, + __lazy_not> + , is_constructible<_Hp, _Tp> >::value >::type @@ -277,12 +278,35 @@ >::value)), "Attempted to construct a reference element in a tuple with an rvalue");} - __tuple_leaf(const __tuple_leaf& __t) = default; - __tuple_leaf(__tuple_leaf&& __t) = default; + using _HpUnref = typename remove_reference<_Hp>::type; + using _CanCopyAssign = integral_constant, is_copy_assignable<_HpUnref>>::value>; + using _CanMoveAssign = integral_constant, is_move_assignable<_HpUnref>>::value>; + + constexpr __tuple_leaf(typename conditional::value, __tuple_leaf, __nat>::type const& __other) + : value(_VSTD::forward(__other.value)) {} + + __tuple_leaf& + operator=(typename conditional<_CanCopyAssign::value, __tuple_leaf, __nat>::type const& __v) { + value = __v.value; + return *this; + } + + __tuple_leaf& + operator=(typename conditional<_CanMoveAssign::value, __tuple_leaf, __nat>::type&& __v) { + value = _VSTD::move(__v.value); + return *this; + } template _LIBCPP_INLINE_VISIBILITY - __tuple_leaf& + typename enable_if<__lazy_and< + integral_constant::value + && !is_same<_Tp&&, __tuple_leaf&&>::value>, + is_assignable<_Hp&, _Tp&&>>::value, + __tuple_leaf&>::type operator=(_Tp&& __t) _NOEXCEPT_((is_nothrow_assignable<_Hp&, _Tp>::value)) { value = _VSTD::forward<_Tp>(__t); @@ -302,10 +326,9 @@ template class __tuple_leaf<_Ip, _Hp, true> - : private _Hp + : _Hp { - __tuple_leaf& operator=(const __tuple_leaf&); public: _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR __tuple_leaf() _NOEXCEPT_(is_nothrow_default_constructible<_Hp>::value) {} @@ -327,7 +350,9 @@ template ::type, __tuple_leaf>> + __lazy_not>, + __lazy_not> + , is_constructible<_Hp, _Tp> >::value >::type @@ -351,12 +376,9 @@ explicit __tuple_leaf(integral_constant, const _Alloc& __a, _Tp&& __t) : _Hp(_VSTD::forward<_Tp>(__t), __a) {} - __tuple_leaf(__tuple_leaf const &) = default; - __tuple_leaf(__tuple_leaf &&) = default; - template _LIBCPP_INLINE_VISIBILITY - __tuple_leaf& + typename enable_if::value, __tuple_leaf&>::type operator=(_Tp&& __t) _NOEXCEPT_((is_nothrow_assignable<_Hp&, _Tp>::value)) { _Hp::operator=(_VSTD::forward<_Tp>(__t)); @@ -475,24 +497,6 @@ return *this; } - __tuple_impl(const __tuple_impl&) = default; - __tuple_impl(__tuple_impl&&) = default; - - _LIBCPP_INLINE_VISIBILITY - __tuple_impl& - operator=(const __tuple_impl& __t) _NOEXCEPT_((__all::value...>::value)) - { - __swallow(__tuple_leaf<_Indx, _Tp>::operator=(static_cast&>(__t).get())...); - return *this; - } - - _LIBCPP_INLINE_VISIBILITY - __tuple_impl& - operator=(__tuple_impl&& __t) _NOEXCEPT_((__all::value...>::value)) - { - __swallow(__tuple_leaf<_Indx, _Tp>::operator=(_VSTD::forward<_Tp>(static_cast<__tuple_leaf<_Indx, _Tp>&>(__t).get()))...); - return *this; - } _LIBCPP_INLINE_VISIBILITY void swap(__tuple_impl& __t) Index: include/utility =================================================================== --- include/utility +++ include/utility @@ -276,6 +276,7 @@ constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t(); #endif + template struct _LIBCPP_TYPE_VIS_ONLY pair { @@ -310,15 +311,20 @@ ) : first(__p.first), second(__p.second) {} -#if !defined(_LIBCPP_CXX03_LANG) - _LIBCPP_INLINE_VISIBILITY pair(const pair& __p) = default; - _LIBCPP_INLINE_VISIBILITY pair(pair&& __p) = default; -#endif + typedef typename remove_reference<_T1>::type _T1Unref; + typedef typename remove_reference<_T2>::type _T2Unref; + + typedef integral_constant::value || is_reference<_T2>::value) + && is_copy_assignable<_T1Unref>::value + && is_copy_assignable<_T2Unref>::value> _CanCopyAssign; + _LIBCPP_INLINE_VISIBILITY - pair& operator=(const pair& __p) - _NOEXCEPT_(is_nothrow_copy_assignable::value && - is_nothrow_copy_assignable::value) + pair& + operator=(typename conditional<_CanCopyAssign::value == true, pair, __nat>::type const& __p) + _NOEXCEPT_(is_nothrow_copy_assignable<_T1Unref>::value && + is_nothrow_copy_assignable<_T2Unref>::value) { first = __p.first; second = __p.second; @@ -344,10 +350,16 @@ : first(_VSTD::forward<_U1>(__p.first)), second(_VSTD::forward<_U2>(__p.second)) {} + typedef integral_constant::value || is_reference<_T2>::value) + && is_move_assignable<_T1Unref>::value + && is_move_assignable<_T2Unref>::value> _CanMoveAssign; + _LIBCPP_INLINE_VISIBILITY pair& - operator=(pair&& __p) _NOEXCEPT_(is_nothrow_move_assignable::value && - is_nothrow_move_assignable::value) + operator=(typename conditional<_CanMoveAssign::value, pair, __nat>::type&& __p) + _NOEXCEPT_(is_nothrow_move_assignable<_T1Unref>::value && + is_nothrow_move_assignable<_T2Unref>::value) { first = _VSTD::forward(__p.first); second = _VSTD::forward(__p.second); Index: test/test.pass.cpp =================================================================== --- /dev/null +++ test/test.pass.cpp @@ -0,0 +1,68 @@ +#include +#include +#include +#include + +#include "test_macros.h" + +struct NonAssignable { +private: + NonAssignable& operator=(NonAssignable const&) _LIBCPP_EQUAL_DELETE; +#if TEST_STD_VER >= 11 + NonAssignable& operator=(NonAssignable&&) _LIBCPP_EQUAL_DELETE; +#endif +}; + +int main() { + typedef std::unique_ptr Ptr; + typedef NonAssignable NA; + { + typedef std::pair T; + const T x(1, 2); + T y; + y = x; + static_assert(std::is_copy_assignable::value, ""); + static_assert(std::is_move_assignable::value, ""); + } +#if TEST_STD_VER >= 11 + { + using T = std::pair; + static_assert(!std::is_copy_assignable::value, ""); + static_assert(std::is_move_assignable::value, ""); + } + { + using T = std::pair; + static_assert(!std::is_copy_assignable::value, ""); + static_assert(std::is_move_assignable::value, ""); + } + { + using T = std::pair; + static_assert(!std::is_copy_assignable::value, ""); + static_assert(std::is_move_assignable::value, ""); + } + { + using T = std::pair; + static_assert(!std::is_copy_assignable::value, ""); + static_assert(!std::is_move_assignable::value, ""); + } + { + using T = std::pair; + static_assert(std::is_copy_assignable::value, ""); + static_assert(std::is_move_assignable::value, ""); + } + { + using T = std::tuple; + static_assert(!std::is_copy_assignable::value, ""); + } + { + using T = std::pair; + static_assert(!std::is_copy_assignable::value, ""); + static_assert(!std::is_move_assignable::value, ""); + } + { + using T = std::tuple; + static_assert(!std::is_copy_assignable::value, ""); + static_assert(!std::is_move_assignable::value, ""); + } +#endif +}