EricWF updated this revision to Diff 60640. EricWF added a comment. Fix merge conflicts with master.
http://reviews.llvm.org/D21314 Files: include/tuple include/utility test/test.pass.cpp
Index: test/test.pass.cpp =================================================================== --- /dev/null +++ test/test.pass.cpp @@ -0,0 +1,68 @@ +#include <utility> +#include <tuple> +#include <type_traits> +#include <memory> + +#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<int> Ptr; + typedef NonAssignable NA; + { + typedef std::pair<int, int> T; + const T x(1, 2); + T y; + y = x; + static_assert(std::is_copy_assignable<T>::value, ""); + static_assert(std::is_move_assignable<T>::value, ""); + } +#if TEST_STD_VER >= 11 + { + using T = std::pair<int, Ptr>; + static_assert(!std::is_copy_assignable<T>::value, ""); + static_assert(std::is_move_assignable<T>::value, ""); + } + { + using T = std::pair<int, Ptr&>; + static_assert(!std::is_copy_assignable<T>::value, ""); + static_assert(std::is_move_assignable<T>::value, ""); + } + { + using T = std::pair<int, Ptr&&>; + static_assert(!std::is_copy_assignable<T>::value, ""); + static_assert(std::is_move_assignable<T>::value, ""); + } + { + using T = std::pair<int, Ptr const&>; + static_assert(!std::is_copy_assignable<T>::value, ""); + static_assert(!std::is_move_assignable<T>::value, ""); + } + { + using T = std::pair<int&, int&&>; + static_assert(std::is_copy_assignable<T>::value, ""); + static_assert(std::is_move_assignable<T>::value, ""); + } + { + using T = std::tuple<int, Ptr>; + static_assert(!std::is_copy_assignable<T>::value, ""); + } + { + using T = std::pair<int, NA>; + static_assert(!std::is_copy_assignable<T>::value, ""); + static_assert(!std::is_move_assignable<T>::value, ""); + } + { + using T = std::tuple<int, NA>; + static_assert(!std::is_copy_assignable<T>::value, ""); + static_assert(!std::is_move_assignable<T>::value, ""); + } +#endif +} Index: include/utility =================================================================== --- include/utility +++ include/utility @@ -276,6 +276,7 @@ constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t(); #endif + template <class _T1, class _T2> 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<bool, + (is_reference<_T1>::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<first_type>::value && - is_nothrow_copy_assignable<second_type>::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<bool, + (is_reference<_T1>::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<first_type>::value && - is_nothrow_move_assignable<second_type>::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<first_type>(__p.first); second = _VSTD::forward<second_type>(__p.second); 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 <class _Tp, class = typename enable_if< __lazy_and< - __lazy_not<is_same<typename decay<_Tp>::type, __tuple_leaf>> + __lazy_not<is_same<_Tp&&, __tuple_leaf const&>>, + __lazy_not<is_same<_Tp&&, __tuple_leaf&&>> + , 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<bool, + __lazy_and<is_reference<_Hp>, is_copy_assignable<_HpUnref>>::value>; + using _CanMoveAssign = integral_constant<bool, + __lazy_and<is_reference<_Hp>, is_move_assignable<_HpUnref>>::value>; + + constexpr __tuple_leaf(typename conditional<is_reference<_Hp>::value, __tuple_leaf, __nat>::type const& __other) + : value(_VSTD::forward<decltype(__other.value)>(__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 <class _Tp> _LIBCPP_INLINE_VISIBILITY - __tuple_leaf& + typename enable_if<__lazy_and< + integral_constant<bool, + !is_same<_Tp&&, __tuple_leaf const&>::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 <size_t _Ip, class _Hp> 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 <class _Tp, class = typename enable_if< __lazy_and< - __lazy_not<is_same<typename decay<_Tp>::type, __tuple_leaf>> + __lazy_not<is_same<_Tp&&, __tuple_leaf const&>>, + __lazy_not<is_same<_Tp&&, __tuple_leaf &&>> + , is_constructible<_Hp, _Tp> >::value >::type @@ -351,12 +376,9 @@ explicit __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a, _Tp&& __t) : _Hp(_VSTD::forward<_Tp>(__t), __a) {} - __tuple_leaf(__tuple_leaf const &) = default; - __tuple_leaf(__tuple_leaf &&) = default; - template <class _Tp> _LIBCPP_INLINE_VISIBILITY - __tuple_leaf& + typename enable_if<is_assignable<_Hp&, _Tp&&>::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<is_nothrow_copy_assignable<_Tp>::value...>::value)) - { - __swallow(__tuple_leaf<_Indx, _Tp>::operator=(static_cast<const __tuple_leaf<_Indx, _Tp>&>(__t).get())...); - return *this; - } - - _LIBCPP_INLINE_VISIBILITY - __tuple_impl& - operator=(__tuple_impl&& __t) _NOEXCEPT_((__all<is_nothrow_move_assignable<_Tp>::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)
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits