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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits