implement more of N4258 - Cleaning up noexcept in the standard library. Specifically add new noexcept stuff to vector and string's move-assignment operations
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@245330 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
fc93ce7349
commit
af961ed8cf
@ -5574,6 +5574,15 @@ template <typename _Alloc>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __swap_allocator(_Alloc &, _Alloc &, false_type) _NOEXCEPT {}
|
||||
|
||||
template <typename _Alloc, typename _Traits=allocator_traits<_Alloc>>
|
||||
struct __noexcept_move_assign_container : public integral_constant<bool,
|
||||
_Traits::propagate_on_container_move_assignment::value
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
|| _Traits::is_always_equal::value
|
||||
#else
|
||||
&& is_nothrow_move_assignable<_Alloc>::value
|
||||
#endif
|
||||
> {};
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
|
@ -115,8 +115,8 @@ public:
|
||||
basic_string& operator=(const basic_string& str);
|
||||
basic_string& operator=(basic_string&& str)
|
||||
noexcept(
|
||||
allocator_type::propagate_on_container_move_assignment::value &&
|
||||
is_nothrow_move_assignable<allocator_type>::value);
|
||||
allocator_type::propagate_on_container_move_assignment::value ||
|
||||
allocator_type::is_always_equal::value ); // C++17
|
||||
basic_string& operator=(const value_type* s);
|
||||
basic_string& operator=(value_type c);
|
||||
basic_string& operator=(initializer_list<value_type>);
|
||||
@ -1377,8 +1377,7 @@ public:
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
basic_string& operator=(basic_string&& __str)
|
||||
_NOEXCEPT_(__alloc_traits::propagate_on_container_move_assignment::value &&
|
||||
is_nothrow_move_assignable<allocator_type>::value);
|
||||
_NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value));
|
||||
#endif
|
||||
_LIBCPP_INLINE_VISIBILITY basic_string& operator=(const value_type* __s) {return assign(__s);}
|
||||
basic_string& operator=(value_type __c);
|
||||
@ -1845,10 +1844,15 @@ private:
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __move_assign(basic_string& __str, false_type);
|
||||
void __move_assign(basic_string& __str, false_type)
|
||||
_NOEXCEPT_(__alloc_traits::is_always_equal::value);
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __move_assign(basic_string& __str, true_type)
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
_NOEXCEPT;
|
||||
#else
|
||||
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
@ -2430,6 +2434,7 @@ template <class _CharT, class _Traits, class _Allocator>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void
|
||||
basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, false_type)
|
||||
_NOEXCEPT_(__alloc_traits::is_always_equal::value)
|
||||
{
|
||||
if (__alloc() != __str.__alloc())
|
||||
assign(__str);
|
||||
@ -2441,7 +2446,11 @@ template <class _CharT, class _Traits, class _Allocator>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
void
|
||||
basic_string<_CharT, _Traits, _Allocator>::__move_assign(basic_string& __str, true_type)
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
_NOEXCEPT
|
||||
#else
|
||||
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value)
|
||||
#endif
|
||||
{
|
||||
clear();
|
||||
shrink_to_fit();
|
||||
@ -2454,8 +2463,7 @@ template <class _CharT, class _Traits, class _Allocator>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
basic_string<_CharT, _Traits, _Allocator>&
|
||||
basic_string<_CharT, _Traits, _Allocator>::operator=(basic_string&& __str)
|
||||
_NOEXCEPT_(__alloc_traits::propagate_on_container_move_assignment::value &&
|
||||
is_nothrow_move_assignable<allocator_type>::value)
|
||||
_NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value))
|
||||
{
|
||||
__move_assign(__str, integral_constant<bool,
|
||||
__alloc_traits::propagate_on_container_move_assignment::value>());
|
||||
|
@ -51,8 +51,8 @@ public:
|
||||
vector& operator=(const vector& x);
|
||||
vector& operator=(vector&& x)
|
||||
noexcept(
|
||||
allocator_type::propagate_on_container_move_assignment::value &&
|
||||
is_nothrow_move_assignable<allocator_type>::value);
|
||||
allocator_type::propagate_on_container_move_assignment::value ||
|
||||
allocator_type::is_always_equal::value); // C++17
|
||||
vector& operator=(initializer_list<value_type> il);
|
||||
template <class InputIterator>
|
||||
void assign(InputIterator first, InputIterator last);
|
||||
@ -175,8 +175,8 @@ public:
|
||||
vector& operator=(const vector& x);
|
||||
vector& operator=(vector&& x)
|
||||
noexcept(
|
||||
allocator_type::propagate_on_container_move_assignment::value &&
|
||||
is_nothrow_move_assignable<allocator_type>::value);
|
||||
allocator_type::propagate_on_container_move_assignment::value ||
|
||||
allocator_type::is_always_equal::value); // C++17
|
||||
vector& operator=(initializer_list<value_type> il);
|
||||
template <class InputIterator>
|
||||
void assign(InputIterator first, InputIterator last);
|
||||
@ -562,9 +562,7 @@ public:
|
||||
vector(vector&& __x, const allocator_type& __a);
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
vector& operator=(vector&& __x)
|
||||
_NOEXCEPT_(
|
||||
__alloc_traits::propagate_on_container_move_assignment::value &&
|
||||
is_nothrow_move_assignable<allocator_type>::value);
|
||||
_NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value));
|
||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
@ -787,7 +785,8 @@ private:
|
||||
void __move_range(pointer __from_s, pointer __from_e, pointer __to);
|
||||
void __move_assign(vector& __c, true_type)
|
||||
_NOEXCEPT_(is_nothrow_move_assignable<allocator_type>::value);
|
||||
void __move_assign(vector& __c, false_type);
|
||||
void __move_assign(vector& __c, false_type)
|
||||
_NOEXCEPT_(__alloc_traits::is_always_equal::value);
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __destruct_at_end(pointer __new_last) _NOEXCEPT
|
||||
{
|
||||
@ -1303,9 +1302,7 @@ template <class _Tp, class _Allocator>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
vector<_Tp, _Allocator>&
|
||||
vector<_Tp, _Allocator>::operator=(vector&& __x)
|
||||
_NOEXCEPT_(
|
||||
__alloc_traits::propagate_on_container_move_assignment::value &&
|
||||
is_nothrow_move_assignable<allocator_type>::value)
|
||||
_NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value))
|
||||
{
|
||||
__move_assign(__x, integral_constant<bool,
|
||||
__alloc_traits::propagate_on_container_move_assignment::value>());
|
||||
@ -1315,6 +1312,7 @@ vector<_Tp, _Allocator>::operator=(vector&& __x)
|
||||
template <class _Tp, class _Allocator>
|
||||
void
|
||||
vector<_Tp, _Allocator>::__move_assign(vector& __c, false_type)
|
||||
_NOEXCEPT_(__alloc_traits::is_always_equal::value)
|
||||
{
|
||||
if (__base::__alloc() != __c.__alloc())
|
||||
{
|
||||
@ -2213,9 +2211,7 @@ public:
|
||||
vector(vector&& __v, const allocator_type& __a);
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
vector& operator=(vector&& __v)
|
||||
_NOEXCEPT_(
|
||||
__alloc_traits::propagate_on_container_move_assignment::value &&
|
||||
is_nothrow_move_assignable<allocator_type>::value);
|
||||
_NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value));
|
||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
#ifndef _LIBCPP_HAS_NO_GENERALIZED_INITIALIZERS
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
@ -2838,9 +2834,7 @@ template <class _Allocator>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
vector<bool, _Allocator>&
|
||||
vector<bool, _Allocator>::operator=(vector&& __v)
|
||||
_NOEXCEPT_(
|
||||
__alloc_traits::propagate_on_container_move_assignment::value &&
|
||||
is_nothrow_move_assignable<allocator_type>::value)
|
||||
_NOEXCEPT_((__noexcept_move_assign_container<_Allocator, __alloc_traits>::value))
|
||||
{
|
||||
__move_assign(__v, integral_constant<bool,
|
||||
__storage_traits::propagate_on_container_move_assignment::value>());
|
||||
|
@ -28,6 +28,32 @@ struct some_alloc
|
||||
some_alloc(const some_alloc&);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct some_alloc2
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
some_alloc2() {}
|
||||
some_alloc2(const some_alloc2&);
|
||||
void deallocate(void*, unsigned) {}
|
||||
|
||||
typedef std::false_type propagate_on_container_move_assignment;
|
||||
typedef std::true_type is_always_equal;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct some_alloc3
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
some_alloc3() {}
|
||||
some_alloc3(const some_alloc3&);
|
||||
void deallocate(void*, unsigned) {}
|
||||
|
||||
typedef std::false_type propagate_on_container_move_assignment;
|
||||
typedef std::false_type is_always_equal;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
#if __has_feature(cxx_noexcept)
|
||||
@ -45,7 +71,22 @@ int main()
|
||||
}
|
||||
{
|
||||
typedef std::vector<bool, some_alloc<bool>> C;
|
||||
#if TEST_STD_VER > 14
|
||||
static_assert( std::is_nothrow_move_assignable<C>::value, "");
|
||||
#else
|
||||
static_assert(!std::is_nothrow_move_assignable<C>::value, "");
|
||||
#endif
|
||||
}
|
||||
#if TEST_STD_VER > 14
|
||||
{ // POCMA false, is_always_equal true
|
||||
typedef std::vector<bool, some_alloc2<bool>> C;
|
||||
static_assert( std::is_nothrow_move_assignable<C>::value, "");
|
||||
}
|
||||
{ // POCMA false, is_always_equal false
|
||||
typedef std::vector<bool, some_alloc3<bool>> C;
|
||||
static_assert(!std::is_nothrow_move_assignable<C>::value, "");
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
@ -29,6 +29,33 @@ struct some_alloc
|
||||
some_alloc(const some_alloc&);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct some_alloc2
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
some_alloc2() {}
|
||||
some_alloc2(const some_alloc2&);
|
||||
void deallocate(void*, unsigned) {}
|
||||
|
||||
typedef std::false_type propagate_on_container_move_assignment;
|
||||
typedef std::true_type is_always_equal;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct some_alloc3
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
some_alloc3() {}
|
||||
some_alloc3(const some_alloc3&);
|
||||
void deallocate(void*, unsigned) {}
|
||||
|
||||
typedef std::false_type propagate_on_container_move_assignment;
|
||||
typedef std::false_type is_always_equal;
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
#if __has_feature(cxx_noexcept)
|
||||
@ -46,7 +73,24 @@ int main()
|
||||
}
|
||||
{
|
||||
typedef std::vector<MoveOnly, some_alloc<MoveOnly>> C;
|
||||
// In C++17, move assignment for allocators are not allowed to throw
|
||||
#if TEST_STD_VER > 14
|
||||
static_assert( std::is_nothrow_move_assignable<C>::value, "");
|
||||
#else
|
||||
static_assert(!std::is_nothrow_move_assignable<C>::value, "");
|
||||
#endif
|
||||
}
|
||||
|
||||
#if TEST_STD_VER > 14
|
||||
{ // POCMA false, is_always_equal true
|
||||
typedef std::vector<MoveOnly, some_alloc2<MoveOnly>> C;
|
||||
static_assert( std::is_nothrow_move_assignable<C>::value, "");
|
||||
}
|
||||
{ // POCMA false, is_always_equal false
|
||||
typedef std::vector<MoveOnly, some_alloc3<MoveOnly>> C;
|
||||
static_assert(!std::is_nothrow_move_assignable<C>::value, "");
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
@ -11,14 +11,18 @@
|
||||
|
||||
// basic_string& operator=(basic_string&& c)
|
||||
// noexcept(
|
||||
// allocator_type::propagate_on_container_move_assignment::value &&
|
||||
// is_nothrow_move_assignable<allocator_type>::value);
|
||||
|
||||
// This tests a conforming extension
|
||||
// allocator_traits<allocator_type>::propagate_on_container_move_assignment::value ||
|
||||
// allocator_traits<allocator_type>::is_always_equal::value); // C++17
|
||||
//
|
||||
// before C++17, we use the conforming extension
|
||||
// noexcept(
|
||||
// allocator_type::propagate_on_container_move_assignment::value &&
|
||||
// is_nothrow_move_assignable<allocator_type>::value);
|
||||
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_allocator.h"
|
||||
|
||||
template <class T>
|
||||
@ -28,6 +32,32 @@ struct some_alloc
|
||||
some_alloc(const some_alloc&);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct some_alloc2
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
some_alloc2() {}
|
||||
some_alloc2(const some_alloc2&);
|
||||
void deallocate(void*, unsigned) {}
|
||||
|
||||
typedef std::false_type propagate_on_container_move_assignment;
|
||||
typedef std::true_type is_always_equal;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct some_alloc3
|
||||
{
|
||||
typedef T value_type;
|
||||
|
||||
some_alloc3() {}
|
||||
some_alloc3(const some_alloc3&);
|
||||
void deallocate(void*, unsigned) {}
|
||||
|
||||
typedef std::false_type propagate_on_container_move_assignment;
|
||||
typedef std::false_type is_always_equal;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
#if __has_feature(cxx_noexcept)
|
||||
@ -41,7 +71,25 @@ int main()
|
||||
}
|
||||
{
|
||||
typedef std::basic_string<char, std::char_traits<char>, some_alloc<char>> C;
|
||||
#if TEST_STD_VER > 14
|
||||
// if the allocators are always equal, then the move assignment can be noexcept
|
||||
static_assert( std::is_nothrow_move_assignable<C>::value, "");
|
||||
#else
|
||||
static_assert(!std::is_nothrow_move_assignable<C>::value, "");
|
||||
#endif
|
||||
}
|
||||
#if TEST_STD_VER > 14
|
||||
{
|
||||
// POCMA is false, always equal
|
||||
typedef std::basic_string<char, std::char_traits<char>, some_alloc2<char>> C;
|
||||
static_assert( std::is_nothrow_move_assignable<C>::value, "");
|
||||
}
|
||||
{
|
||||
// POCMA is false, not always equal
|
||||
typedef std::basic_string<char, std::char_traits<char>, some_alloc3<char>> C;
|
||||
static_assert(!std::is_nothrow_move_assignable<C>::value, "");
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user