EricWF created this revision. EricWF added reviewers: mclow.lists, rsmith, K-ballo. EricWF added a subscriber: cfe-commits.
This shows the basic jist of my proposed changes. I haven't tested them enough to ensure they are 100% correct. Can anybody suggest a better solution? http://reviews.llvm.org/D21314 Files: include/utility test/test.pass.cpp
Index: test/test.pass.cpp =================================================================== --- /dev/null +++ test/test.pass.cpp @@ -0,0 +1,54 @@ +#include <utility> +#include <tuple> +#include <type_traits> +#include <memory> + +struct NonAssignable { + NonAssignable& operator=(NonAssignable const&) = delete; + NonAssignable& operator=(NonAssignable&&) = delete; + +}; + +int main() { + using Ptr = std::unique_ptr<int>; + using NA = NonAssignable; + { + 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, ""); + } +} \ No newline at end of file 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 { @@ -323,11 +324,20 @@ { } #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 const&, __nat&>::type __p) + _NOEXCEPT_(is_nothrow_copy_assignable<_T1Unref>::value && + is_nothrow_copy_assignable<_T2Unref>::value) { first = __p.first; second = __p.second; @@ -365,11 +375,16 @@ { } #endif + 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);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits