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 53e6f82 commit 63a7943
Show file tree
Hide file tree
Showing 10 changed files with 2,096 additions and 478 deletions.
1,062 changes: 649 additions & 413 deletions stl/inc/vector

Large diffs are not rendered by default.

169 changes: 104 additions & 65 deletions stl/inc/xmemory
Original file line number Diff line number Diff line change
Expand Up @@ -1598,18 +1598,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 @@ -1643,18 +1643,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 @@ -1690,22 +1695,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 @@ -1719,7 +1725,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 @@ -1730,17 +1736,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 @@ -1783,25 +1794,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 @@ -1839,7 +1861,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 @@ -1848,16 +1870,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 @@ -1904,27 +1930,36 @@ _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;
}
} 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
{
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 @@ -2028,22 +2063,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 63a7943

Please sign in to comment.