Skip to content
Permalink
Browse files

std::vector now uses the `is_trivially_relocatable` type trait.

The following internal type traits are added:

- `__has_trivial_move_construct<A, T>`
- `__has_trivial_destroy<A, T>`
- `__has_trivial_construct_and_destroy<A, T>`

And the following public type traits:

- `allocator_traits<A>::has_trivial_construct_and_destroy<T>`
- `is_trivially_relocatable<T>`
- `is_trivially_relocatable_v<T>`
- `_LIBCPP_SUPPORTS_TRIVIALLY_RELOCATABLE`
  • Loading branch information...
Quuxplusone committed Apr 14, 2018
1 parent 8dd2afa commit 34eb0b5c8f03880b94d53b877cbca384783ad65a
Showing with 112 additions and 12 deletions.
  1. +2 −0 include/__config
  2. +41 −9 include/memory
  3. +28 −0 include/type_traits
  4. +41 −3 include/vector
@@ -1323,6 +1323,8 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
# endif // defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_BUILDING_LIBRARY)
#endif // _LIBCPP_NO_AUTO_LINK

#define _LIBCPP_SUPPORTS_TRIVIALLY_RELOCATABLE

#endif // __cplusplus

#endif // _LIBCPP_CONFIG
@@ -1509,6 +1509,40 @@ struct __alloc_traits_difference_type<_Alloc, _Ptr, true>
typedef typename _Alloc::difference_type type;
};

template <class _Alloc, class _Tp, class = void>
struct __has_has_trivial_construct_and_destroy : false_type {};

template <class _Alloc, class _Tp>
struct __has_has_trivial_construct_and_destroy<_Alloc, _Tp,
typename __void_t<typename _Alloc::template has_trivial_construct_and_destroy<_Tp>>::type>
: true_type {};

template <class _Alloc, class _Tp, bool = __has_has_trivial_construct_and_destroy<_Alloc, _Tp>::value>
struct __has_trivial_construct_and_destroy
: integral_constant<bool, _Alloc::template has_trivial_construct_and_destroy<_Tp>::value> {};

template <class _Alloc, class _Tp>
struct __has_trivial_construct_and_destroy<_Alloc, _Tp, false>
: integral_constant<bool,
!__has_construct<_Alloc, _Tp*, _Tp&&>::value && !__has_destroy<_Alloc, _Tp*>::value> {};

template <class _Tp>
struct __has_trivial_construct_and_destroy<allocator<_Tp>, _Tp, false>
: true_type {};

template <class _Alloc, class _Tp>
struct __has_trivial_move_construct : integral_constant<bool,
__has_trivial_construct_and_destroy<_Alloc, _Tp>::value ||
!__has_construct<_Alloc, _Tp*, _Tp&&>::value
> {};

template <class _Alloc, class _Tp>
struct __has_trivial_destroy : integral_constant<bool,
__has_trivial_construct_and_destroy<_Alloc, _Tp>::value ||
!__has_destroy<_Alloc, _Tp*>::value
> {};


template <class _Alloc>
struct _LIBCPP_TEMPLATE_VIS allocator_traits
{
@@ -1532,6 +1566,10 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits
typedef typename __is_always_equal<allocator_type>::type
is_always_equal;

template<class _Tp>
using has_trivial_construct_and_destroy =
typename __has_trivial_construct_and_destroy<allocator_type, _Tp>::type;

#ifndef _LIBCPP_CXX03_LANG
template <class _Tp> using rebind_alloc =
typename __allocator_traits_rebind<allocator_type, _Tp>::type;
@@ -1671,7 +1709,7 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits
_LIBCPP_INLINE_VISIBILITY
static
void
__construct_backward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2)
__construct_backward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2, false_type)
{
while (__end1 != __begin1)
{
@@ -1683,14 +1721,8 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY
static
typename enable_if
<
(is_same<allocator_type, allocator<_Tp> >::value
|| !__has_construct<allocator_type, _Tp*, _Tp>::value) &&
is_trivially_move_constructible<_Tp>::value,
void
>::type
__construct_backward(allocator_type&, _Tp* __begin1, _Tp* __end1, _Tp*& __end2)
void
__construct_backward(allocator_type&, _Tp* __begin1, _Tp* __end1, _Tp*& __end2, true_type)
{
ptrdiff_t _Np = __end1 - __begin1;
__end2 -= _Np;
@@ -3694,6 +3694,34 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_trivially_destructible_v
= is_trivially_destructible<_Tp>::value;
#endif

// is_trivially_relocatable

template <class _Tp, class = void> struct __is_trivially_relocatable_check
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
: public integral_constant<bool,
is_trivially_move_constructible<_Tp>::value && is_trivially_destructible<_Tp>::value
>
#else
: public integral_constant<bool,
is_trivially_copy_constructible<_Tp>::value && is_trivially_destructible<_Tp>::value
>
#endif
{};

template <class _Tp> struct __is_trivially_relocatable_check<_Tp, decltype(void(bool(_Tp::is_trivially_relocatable::value)))>
: integral_constant<bool, _Tp::is_trivially_relocatable::value>
{};

template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_trivially_relocatable
: public __is_trivially_relocatable_check<_Tp, void>
{};

#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
template <class _Tp>
_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_trivially_relocatable_v
= is_trivially_relocatable<_Tp>::value;
#endif

// is_nothrow_constructible

#if 0
@@ -894,12 +894,31 @@ template <class _Tp, class _Allocator>
void
vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v)
{
using __copy_via_memcpy = integral_constant<bool,
(
__has_trivial_move_construct<allocator_type, value_type>::value &&
is_trivially_move_constructible<_Tp>::value
) || (
__has_trivial_construct_and_destroy<allocator_type, value_type>::value &&
is_trivially_relocatable<_Tp>::value
)>;

using __destroy_via_noop = integral_constant<bool,
(
__has_trivial_destroy<allocator_type, value_type>::value &&
is_trivially_destructible<_Tp>::value
) || (
__has_trivial_construct_and_destroy<allocator_type, value_type>::value &&
is_trivially_relocatable<_Tp>::value
)>;

__annotate_delete();
__alloc_traits::__construct_backward(this->__alloc(), this->__begin_, this->__end_, __v.__begin_);
__alloc_traits::__construct_backward(this->__alloc(), this->__begin_, this->__end_, __v.__begin_, __copy_via_memcpy{});
_VSTD::swap(this->__begin_, __v.__begin_);
_VSTD::swap(this->__end_, __v.__end_);
_VSTD::swap(this->__end_cap(), __v.__end_cap());
__v.__first_ = __v.__begin_;
__v.__destruct_at_end(__v.__begin_, __destroy_via_noop{});
__annotate_new(size());
__invalidate_all_iterators();
}
@@ -908,14 +927,33 @@ template <class _Tp, class _Allocator>
typename vector<_Tp, _Allocator>::pointer
vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v, pointer __p)
{
using __copy_via_memcpy = integral_constant<bool,
(
__has_trivial_move_construct<allocator_type, value_type>::value &&
is_trivially_move_constructible<_Tp>::value
) || (
__has_trivial_construct_and_destroy<allocator_type, value_type>::value &&
is_trivially_relocatable<_Tp>::value
)>;

using __destroy_via_noop = integral_constant<bool,
(
__has_trivial_destroy<allocator_type, value_type>::value &&
is_trivially_destructible<_Tp>::value
) || (
__has_trivial_construct_and_destroy<allocator_type, value_type>::value &&
is_trivially_relocatable<_Tp>::value
)>;

__annotate_delete();
pointer __r = __v.__begin_;
__alloc_traits::__construct_backward(this->__alloc(), this->__begin_, __p, __v.__begin_);
__alloc_traits::__construct_forward(this->__alloc(), __p, this->__end_, __v.__end_);
__alloc_traits::__construct_backward(this->__alloc(), this->__begin_, __p, __v.__begin_, __copy_via_memcpy{});
__alloc_traits::__construct_forward(this->__alloc(), __p, this->__end_, __v.__end_, __copy_via_memcpy{});
_VSTD::swap(this->__begin_, __v.__begin_);
_VSTD::swap(this->__end_, __v.__end_);
_VSTD::swap(this->__end_cap(), __v.__end_cap());
__v.__first_ = __v.__begin_;
__v.__destruct_at_end(__v.__begin_, __destroy_via_noop{});
__annotate_new(size());
__invalidate_all_iterators();
return __r;

0 comments on commit 34eb0b5

Please sign in to comment.
You can’t perform that action at this time.