EricWF retitled this revision from "Make pair respect is_copy_assignable and
is_move_assignable" to "Make pair and tuple respect is_copy_assignable and
is_move_assignable".
EricWF updated this revision to Diff 60631.
EricWF added a comment.
- Remove `= default` copy/move constructors in pair. Let the compiler
implicitly mark them as default.
- Roughly implement the changes in `<tuple>` This still needs a ton more tests.
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
+}
\ 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
{
@@ -310,10 +311,7 @@
)
: first(__p.first), second(__p.second) {}
-#if !defined(_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS) && _LIBCPP_TRIVIAL_PAIR_COPY_CTOR
- _LIBCPP_INLINE_VISIBILITY
- pair(const pair& __p) = default;
-#elif !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) || !_LIBCPP_TRIVIAL_PAIR_COPY_CTOR
+#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) || !_LIBCPP_TRIVIAL_PAIR_COPY_CTOR
_LIBCPP_INLINE_VISIBILITY
pair(const pair& __p)
_NOEXCEPT_(is_nothrow_copy_constructible<first_type>::value &&
@@ -323,11 +321,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;
@@ -353,23 +360,25 @@
: first(_VSTD::forward<_U1>(__p.first)),
second(_VSTD::forward<_U2>(__p.second)) {}
-#ifndef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS
- _LIBCPP_INLINE_VISIBILITY
- pair(pair&& __p) = default;
-#else
+#ifdef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS
_LIBCPP_INLINE_VISIBILITY
pair(pair&& __p) _NOEXCEPT_(is_nothrow_move_constructible<first_type>::value &&
is_nothrow_move_constructible<second_type>::value)
: first(_VSTD::forward<first_type>(__p.first)),
second(_VSTD::forward<second_type>(__p.second))
{
}
#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);
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()
@@ -280,6 +279,25 @@
__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,
+ is_reference<_Hp>::value && is_copy_assignable<_HpUnref>::value>;
+ using _CanMoveAssign = integral_constant<bool,
+ is_reference<_Hp>::value && is_move_assignable<_HpUnref>::value>;
+#if 1
+ __tuple_leaf&
+ operator=(typename conditional<_CanCopyAssign::value, __tuple_leaf const&, __nat&>::type __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;
+ }
+#endif
+
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY
__tuple_leaf&
@@ -356,7 +374,7 @@
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY
- __tuple_leaf&
+ typename enable_if<!is_same<typename decay<_Tp>::type, __tuple_leaf>::value, __tuple_leaf&>::type
operator=(_Tp&& __t) _NOEXCEPT_((is_nothrow_assignable<_Hp&, _Tp>::value))
{
_Hp::operator=(_VSTD::forward<_Tp>(__t));
@@ -477,22 +495,9 @@
__tuple_impl(const __tuple_impl&) = default;
__tuple_impl(__tuple_impl&&) = default;
+ __tuple_impl& operator=(__tuple_impl const&) = default;
+ __tuple_impl& operator=(__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
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits