Skip to content

Commit

Permalink
[P1004] Implement constexpr vector
Browse files Browse the repository at this point in the history
  • Loading branch information
miscco committed Dec 21, 2020
1 parent 9e47267 commit dab4ff9
Show file tree
Hide file tree
Showing 10 changed files with 2,101 additions and 484 deletions.
1,058 changes: 645 additions & 413 deletions stl/inc/vector

Large diffs are not rendered by default.

184 changes: 113 additions & 71 deletions stl/inc/xmemory
Original file line number Diff line number Diff line change
Expand Up @@ -1176,9 +1176,7 @@ public:
_Container_base12& operator=(const _Container_base12&) = delete;

_CONSTEXPR20_DYNALLOC void _Orphan_all() noexcept;
inline void _Orphan_all_impl() noexcept;
_CONSTEXPR20_DYNALLOC void _Swap_proxy_and_iterators(_Container_base12&) noexcept;
inline void _Swap_proxy_and_iterators_impl(_Container_base12&) noexcept;

template <class _Alloc>
_CONSTEXPR20_DYNALLOC void _Alloc_proxy(_Alloc&& _Al) {
Expand Down Expand Up @@ -1208,6 +1206,10 @@ public:
}

_Container_proxy* _Myproxy;

private:
inline void _Orphan_all_impl() noexcept;
inline void _Swap_proxy_and_iterators_impl(_Container_base12&) noexcept;
};

struct _Iterator_base12 { // store links to container proxy, next iterator
Expand Down Expand Up @@ -1411,8 +1413,8 @@ struct _Container_proxy_ptr12 : _Basic_container_proxy_ptr12 {
// smart pointer components for a _Container_proxy * for an allocator family
_Alloc& _Al;

_CONSTEXPR20_DYNALLOC _Container_proxy_ptr12(_Alloc& _Al_, _Leave_proxy_unbound)
: _Al(_Al_) { // create a new unbound _Container_proxy
_CONSTEXPR20_DYNALLOC _Container_proxy_ptr12(_Alloc& _Al_, _Leave_proxy_unbound) : _Al(_Al_) {
// create a new unbound _Container_proxy
#ifdef __cpp_lib_is_constant_evaluated
if (!_STD is_constant_evaluated())
#endif // __cpp_lib_is_constant_evaluated
Expand All @@ -1422,8 +1424,8 @@ struct _Container_proxy_ptr12 : _Basic_container_proxy_ptr12 {
}
}

_CONSTEXPR20_DYNALLOC _Container_proxy_ptr12(_Alloc& _Al_, _Container_base12& _Mycont)
: _Al(_Al_) { // create a new _Container_proxy pointing at _Mycont
_CONSTEXPR20_DYNALLOC _Container_proxy_ptr12(_Alloc& _Al_, _Container_base12& _Mycont) : _Al(_Al_) {
// create a new _Container_proxy pointing at _Mycont
#ifdef __cpp_lib_is_constant_evaluated
if (!_STD is_constant_evaluated())
#endif // __cpp_lib_is_constant_evaluated
Expand Down Expand Up @@ -1589,18 +1591,18 @@ struct _NODISCARD _Uninitialized_backout {
_Uninitialized_backout(const _Uninitialized_backout&) = delete;
_Uninitialized_backout& operator=(const _Uninitialized_backout&) = delete;

~_Uninitialized_backout() {
_CONSTEXPR20_DYNALLOC ~_Uninitialized_backout() {
_Destroy_range(_First, _Last);
}

template <class... _Types>
void _Emplace_back(_Types&&... _Vals) {
_CONSTEXPR20_DYNALLOC void _Emplace_back(_Types&&... _Vals) {
// construct a new element at *_Last and increment
_Construct_in_place(*_Last, _STD forward<_Types>(_Vals)...);
++_Last;
}

_NoThrowFwdIt _Release() { // suppress any exception handling backout and return _Last
constexpr _NoThrowFwdIt _Release() { // suppress any exception handling backout and return _Last
_First = _Last;
return _Last;
}
Expand Down Expand Up @@ -1634,18 +1636,23 @@ namespace ranges {
// FUNCTION TEMPLATE _Uninitialized_move_unchecked
#if _HAS_IF_CONSTEXPR
template <class _InIt, class _NoThrowFwdIt>
_NoThrowFwdIt _Uninitialized_move_unchecked(_InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) {
_CONSTEXPR20_DYNALLOC _NoThrowFwdIt _Uninitialized_move_unchecked(
_InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) {
// move [_First, _Last) to raw [_Dest, ...)
if constexpr (_Ptr_move_cat<_InIt, _NoThrowFwdIt>::_Really_trivial) {
return _Copy_memmove(_First, _Last, _Dest);
} else {
_Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest};
for (; _First != _Last; ++_First) {
_Backout._Emplace_back(_STD move(*_First));
#ifdef __cpp_lib_is_constant_evaluated
if (!_STD is_constant_evaluated())
#endif // __cpp_lib_is_constant_evaluated
{
return _Copy_memmove(_First, _Last, _Dest);
}

return _Backout._Release();
}
_Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest};
for (; _First != _Last; ++_First) {
_Backout._Emplace_back(_STD move(*_First));
}

return _Backout._Release();
}
#else // ^^^ _HAS_IF_CONSTEXPR ^^^ // vvv !_HAS_IF_CONSTEXPR vvv
template <class _InIt, class _NoThrowFwdIt>
Expand Down Expand Up @@ -1681,22 +1688,23 @@ class _NODISCARD _Uninitialized_backout_al {
using pointer = _Alloc_ptr_t<_Alloc>;

public:
_Uninitialized_backout_al(pointer _Dest, _Alloc& _Al_) : _First(_Dest), _Last(_Dest), _Al(_Al_) {}
_CONSTEXPR20_DYNALLOC _Uninitialized_backout_al(pointer _Dest, _Alloc& _Al_)
: _First(_Dest), _Last(_Dest), _Al(_Al_) {}

_Uninitialized_backout_al(const _Uninitialized_backout_al&) = delete;
_Uninitialized_backout_al& operator=(const _Uninitialized_backout_al&) = delete;

~_Uninitialized_backout_al() {
_CONSTEXPR20_DYNALLOC ~_Uninitialized_backout_al() {
_Destroy_range(_First, _Last, _Al);
}

template <class... _Types>
void _Emplace_back(_Types&&... _Vals) { // construct a new element at *_Last and increment
_CONSTEXPR20_DYNALLOC void _Emplace_back(_Types&&... _Vals) { // construct a new element at *_Last and increment
allocator_traits<_Alloc>::construct(_Al, _Unfancy(_Last), _STD forward<_Types>(_Vals)...);
++_Last;
}

pointer _Release() { // suppress any exception handling backout and return _Last
_CONSTEXPR20_DYNALLOC pointer _Release() { // suppress any exception handling backout and return _Last
_First = _Last;
return _Last;
}
Expand All @@ -1710,7 +1718,7 @@ private:
// FUNCTION TEMPLATE _Uninitialized_copy WITH ALLOCATOR
#if _HAS_IF_CONSTEXPR
template <class _InIt, class _Alloc>
_Alloc_ptr_t<_Alloc> _Uninitialized_copy(
_CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_copy(
const _InIt _First, const _InIt _Last, _Alloc_ptr_t<_Alloc> _Dest, _Alloc& _Al) {
// copy [_First, _Last) to raw _Dest, using _Al
// note: only called internally from elsewhere in the STL
Expand All @@ -1721,17 +1729,22 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_copy(

if constexpr (conjunction_v<bool_constant<_Ptr_copy_cat<decltype(_UFirst), _Ptrval>::_Really_trivial>,
_Uses_default_construct<_Alloc, _Ptrval, decltype(*_UFirst)>>) {
_Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest));
_Dest += _ULast - _UFirst;
} else {
_Uninitialized_backout_al<_Alloc> _Backout{_Dest, _Al};
for (; _UFirst != _ULast; ++_UFirst) {
_Backout._Emplace_back(*_UFirst);
#ifdef __cpp_lib_is_constant_evaluated
if (!_STD is_constant_evaluated())
#endif // __cpp_lib_is_constant_evaluated
{
_Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest));
_Dest += _ULast - _UFirst;
return _Dest;
}

_Dest = _Backout._Release();
}
_Uninitialized_backout_al<_Alloc> _Backout{_Dest, _Al};
for (; _UFirst != _ULast; ++_UFirst) {
_Backout._Emplace_back(*_UFirst);
}

_Dest = _Backout._Release();

return _Dest;
}
#else // ^^^ _HAS_IF_CONSTEXPR ^^^ // vvv !_HAS_IF_CONSTEXPR vvv
Expand Down Expand Up @@ -1774,25 +1787,36 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_copy(

// FUNCTION TEMPLATE uninitialized_copy
#if _HAS_IF_CONSTEXPR
template <class _InIt, class _NoThrowFwdIt>
_CONSTEXPR20_DYNALLOC _NoThrowFwdIt _Uninitialized_copy_unchecked(
_InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) {
// copy [_First, _Last) to raw [_Dest, ...)
if constexpr (_Ptr_move_cat<_InIt, _NoThrowFwdIt>::_Really_trivial) {
#ifdef __cpp_lib_is_constant_evaluated
if (!_STD is_constant_evaluated())
#endif // __cpp_lib_is_constant_evaluated
{
return _Copy_memmove(_First, _Last, _Dest);
}
}
_Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest};
for (; _First != _Last; ++_First) {
_Backout._Emplace_back(*_First);
}

_Dest = _Backout._Release();

return _Dest;
}

template <class _InIt, class _NoThrowFwdIt>
_NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrowFwdIt _Dest) {
// copy [_First, _Last) to raw [_Dest, ...)
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
auto _UDest = _Get_unwrapped_n(_Dest, _Idl_distance<_InIt>(_UFirst, _ULast));
if constexpr (_Ptr_copy_cat<decltype(_UFirst), decltype(_UDest)>::_Really_trivial) {
_UDest = _Copy_memmove(_UFirst, _ULast, _UDest);
} else {
_Uninitialized_backout<decltype(_UDest)> _Backout{_UDest};
for (; _UFirst != _ULast; ++_UFirst) {
_Backout._Emplace_back(*_UFirst);
}

_UDest = _Backout._Release();
}

_Seek_wrapped(_Dest, _UDest);
_Seek_wrapped(_Dest, _Uninitialized_copy_unchecked(_UFirst, _ULast, _UDest));
return _Dest;
}
#else // ^^^ _HAS_IF_CONSTEXPR / !_HAS_IF_CONSTEXPR vvv
Expand Down Expand Up @@ -1830,7 +1854,7 @@ _NoThrowFwdIt uninitialized_copy(const _InIt _First, const _InIt _Last, _NoThrow
// FUNCTION TEMPLATE _Uninitialized_move WITH ALLOCATOR
#if _HAS_IF_CONSTEXPR
template <class _InIt, class _Alloc>
_Alloc_ptr_t<_Alloc> _Uninitialized_move(
_CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_move(
const _InIt _First, const _InIt _Last, _Alloc_ptr_t<_Alloc> _Dest, _Alloc& _Al) {
// move [_First, _Last) to raw _Dest, using _Al
// note: only called internally from elsewhere in the STL
Expand All @@ -1839,16 +1863,20 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_move(
const auto _ULast = _Get_unwrapped(_Last);
if constexpr (conjunction_v<bool_constant<_Ptr_move_cat<decltype(_UFirst), _Ptrval>::_Really_trivial>,
_Uses_default_construct<_Alloc, _Ptrval, decltype(_STD move(*_UFirst))>>) {
_Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest));
return _Dest + (_ULast - _UFirst);
} else {
_Uninitialized_backout_al<_Alloc> _Backout{_Dest, _Al};
for (; _UFirst != _ULast; ++_UFirst) {
_Backout._Emplace_back(_STD move(*_UFirst));
#ifdef __cpp_lib_is_constant_evaluated
if (!_STD is_constant_evaluated())
#endif // __cpp_lib_is_constant_evaluated
{
_Copy_memmove(_UFirst, _ULast, _Unfancy(_Dest));
return _Dest + (_ULast - _UFirst);
}

return _Backout._Release();
}
_Uninitialized_backout_al<_Alloc> _Backout{_Dest, _Al};
for (; _UFirst != _ULast; ++_UFirst) {
_Backout._Emplace_back(_STD move(*_UFirst));
}

return _Backout._Release();
}
#else // ^^^ _HAS_IF_CONSTEXPR ^^^ // vvv !_HAS_IF_CONSTEXPR vvv
template <class _InIt, class _Alloc>
Expand Down Expand Up @@ -1895,27 +1923,37 @@ _Alloc_ptr_t<_Alloc> _Uninitialized_move(
// FUNCTION TEMPLATE _Uninitialized_fill_n WITH ALLOCATOR
#if _HAS_IF_CONSTEXPR
template <class _Alloc>
_Alloc_ptr_t<_Alloc> _Uninitialized_fill_n(
_CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_fill_n(
_Alloc_ptr_t<_Alloc> _First, _Alloc_size_t<_Alloc> _Count, const typename _Alloc::value_type& _Val, _Alloc& _Al) {
// copy _Count copies of _Val to raw _First, using _Al
using _Ty = typename _Alloc::value_type;
if constexpr (_Fill_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) {
_Fill_memset(_Unfancy(_First), _Val, static_cast<size_t>(_Count));
return _First + _Count;
} else {
if constexpr (_Fill_zero_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) {
#ifdef __cpp_lib_is_constant_evaluated
if (!_STD is_constant_evaluated())
#endif // __cpp_lib_is_constant_evaluated
{
_Fill_memset(_Unfancy(_First), _Val, static_cast<size_t>(_Count));
return _First + _Count;
}
}
if constexpr (_Fill_zero_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) {
#ifdef __cpp_lib_is_constant_evaluated
if (!_STD is_constant_evaluated())
#endif // __cpp_lib_is_constant_evaluated
{
if (_Is_all_bits_zero(_Val)) {
_Fill_zero_memset(_Unfancy(_First), static_cast<size_t>(_Count));
return _First + _Count;
}
}
_Uninitialized_backout_al<_Alloc> _Backout{_First, _Al};
for (; 0 < _Count; --_Count) {
_Backout._Emplace_back(_Val);
}
}
_Uninitialized_backout_al<_Alloc> _Backout{_First, _Al};

return _Backout._Release();
for (; 0 < _Count; --_Count) {
_Backout._Emplace_back(_Val);
}

return _Backout._Release();
}
#else // ^^^ _HAS_IF_CONSTEXPR // !_HAS_IF_CONSTEXPR vvv
template <class _Alloc>
Expand Down Expand Up @@ -2019,22 +2057,26 @@ _Ptr _Zero_range(const _Ptr _First, const _Ptr _Last) { // fill [_First, _Last)

#if _HAS_IF_CONSTEXPR
template <class _Alloc>
_Alloc_ptr_t<_Alloc> _Uninitialized_value_construct_n(
_CONSTEXPR20_DYNALLOC _Alloc_ptr_t<_Alloc> _Uninitialized_value_construct_n(
_Alloc_ptr_t<_Alloc> _First, _Alloc_size_t<_Alloc> _Count, _Alloc& _Al) {
// value-initialize _Count objects to raw _First, using _Al
using _Ptrty = typename _Alloc::value_type*;
if constexpr (_Use_memset_value_construct_v<_Ptrty> && _Uses_default_construct<_Alloc, _Ptrty>::value) {
auto _PFirst = _Unfancy(_First);
_Zero_range(_PFirst, _PFirst + _Count);
return _First + _Count;
} else {
_Uninitialized_backout_al<_Alloc> _Backout{_First, _Al};
for (; 0 < _Count; --_Count) {
_Backout._Emplace_back();
#ifdef __cpp_lib_is_constant_evaluated
if (!_STD is_constant_evaluated())
#endif // __cpp_lib_is_constant_evaluated
{
auto _PFirst = _Unfancy(_First);
_Zero_range(_PFirst, _PFirst + _Count);
return _First + _Count;
}

return _Backout._Release();
}
_Uninitialized_backout_al<_Alloc> _Backout{_First, _Al};
for (; 0 < _Count; --_Count) {
_Backout._Emplace_back();
}

return _Backout._Release();
}
#else // ^^^ _HAS_IF_CONSTEXPR // !_HAS_IF_CONSTEXPR vvv
template <class _Alloc>
Expand Down
5 changes: 5 additions & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@
// P0919R3 Heterogeneous Lookup For Unordered Containers
// P0966R1 string::reserve() Should Not Shrink
// P1001R2 execution::unseq
// P1004R2 constexpr std::vector
// P1006R1 constexpr For pointer_traits<T*>::pointer_to()
// P1007R3 assume_aligned()
// P1020R1 Smart Pointer Creation With Default Initialization
Expand Down Expand Up @@ -1204,6 +1205,10 @@
#define __cpp_lib_constexpr_tuple 201811L
#define __cpp_lib_constexpr_utility 201811L

#if defined(__cpp_constexpr_dynamic_alloc) && defined(__clang__) // TRANSITION, ADO1256891, ADO1256895
#define __cpp_lib_constexpr_vector 201907L
#endif // __cpp_constexpr_dynamic_alloc && __clang__

#ifdef __cpp_impl_coroutine // TRANSITION, Clang coroutine support
#define __cpp_lib_coroutine 201902L
#endif // __cpp_impl_coroutine
Expand Down
3 changes: 3 additions & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ tests\P0758R1_is_nothrow_convertible
tests\P0768R1_spaceship_cpos
tests\P0768R1_spaceship_operator
tests\P0769R2_shift_left_shift_right
tests\P0784R7_library_machinery
tests\P0784R7_library_support_for_more_constexpr_containers
tests\P0811R3_midpoint_lerp
tests\P0896R4_common_iterator
Expand Down Expand Up @@ -368,6 +369,8 @@ tests\P0898R3_identity
tests\P0912R5_coroutine
tests\P0919R3_heterogeneous_unordered_lookup
tests\P0966R1_string_reserve_should_not_shrink
tests\P1004R2_constexpr_vector
tests\P1004R2_constexpr_vector_bool
tests\P1007R3_assume_aligned
tests\P1020R1_smart_pointer_for_overwrite
tests\P1023R0_constexpr_for_array_comparisons
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P0784R7_library_machinery/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_latest_matrix.lst
Loading

0 comments on commit dab4ff9

Please sign in to comment.