Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ed4a1ed
Avoid triggering GH-1030 in P0896R4_ranges_alg_equal (#1239)
CaseyCarter Aug 28, 2020
b90b3e0
Fix locale test for older OSes (#1240)
StephanTLavavej Aug 28, 2020
3b2956b
Latch, Semaphore, Barrier (part of #52, P1135R6) (#1057)
AlexGuteniev Sep 1, 2020
e652e72
Implement views::all and views::reverse (#1229)
CaseyCarter Sep 1, 2020
d194462
Implement non-concepts fallback for coroutine_handle operator<=> (#1249)
CaseyCarter Sep 2, 2020
30e7a1b
Implement common_iterator (#1092)
miscco Sep 4, 2020
d6f32c8
Use memset and memcmp in a bit more cases (#1160)
AdamBucior Sep 4, 2020
fcd8a62
Implement ranges::partial_sort and ranges::partial_sort_copy (#1231)
CaseyCarter Sep 4, 2020
ab2081a
Cleanup conditional explicit clauses (#1241)
miscco Sep 4, 2020
8c85c6a
P1391R4 "Range Constructor for string_view" (#1245)
CaseyCarter Sep 4, 2020
2521e64
Add bound check assertion to valarray::operator[] (#1247)
Arzaghi Sep 4, 2020
154f9a8
Replace 0 with nullptr where appropriate (#1250)
SunnyWar Sep 4, 2020
37cd02e
Implement views::filter (#1252)
CaseyCarter Sep 4, 2020
6156ec3
Revert "Implement common_iterator (#1092)" (#1265)
CaseyCarter Sep 4, 2020
0c2007a
Implement views::take and views::drop (#1253)
CaseyCarter Sep 5, 2020
4f72f78
Implement views::transform (#1258)
CaseyCarter Sep 5, 2020
be0441c
enforce "non-array trivial standard-layout" for basic_string and basi…
fsb4000 Sep 5, 2020
9e76d8c
Enable __cpp_lib_concepts for IntelliSense (#1286)
rpjohnst Sep 11, 2020
0e4f6b5
Revert "Revert "Implement common_iterator (#1092)" (#1265)" (#1268)
CaseyCarter Sep 16, 2020
10c4fec
Integrate P1391 into views::take and views::drop (#1271)
CaseyCarter Sep 16, 2020
5a4f64b
Update yvals_core.h (#1272)
Madhvan-Sharma Sep 16, 2020
5f3e912
VS 2019 16.8 Preview 3 toolset update (#1290)
StephanTLavavej Sep 16, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ Just try to follow these rules, so we can spend more time fixing bugs and implem
The STL uses boost-math headers to provide P0226R1 Mathematical Special Functions. We recommend using [vcpkg][] to
acquire this dependency.

1. Install Visual Studio 2019 16.8 Preview 2 or later.
1. Install Visual Studio 2019 16.8 Preview 3 or later.
* We recommend selecting "C++ CMake tools for Windows" in the VS Installer.
This will ensure that you're using supported versions of CMake and Ninja.
* Otherwise, install [CMake][] 3.17 or later, and [Ninja][] 1.8.2 or later.
Expand All @@ -158,7 +158,7 @@ acquire this dependency.

# How To Build With A Native Tools Command Prompt

1. Install Visual Studio 2019 16.8 Preview 2 or later.
1. Install Visual Studio 2019 16.8 Preview 3 or later.
* We recommend selecting "C++ CMake tools for Windows" in the VS Installer.
This will ensure that you're using supported versions of CMake and Ninja.
* Otherwise, install [CMake][] 3.17 or later, and [Ninja][] 1.8.2 or later.
Expand Down
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# Build STL targeting x86, x64, arm, arm64

variables:
agentPool: 'StlBuild-2020-08-26'
agentPool: 'StlBuild-2020-09-14'
tmpDir: 'D:\Temp'

stages:
Expand Down
3 changes: 3 additions & 0 deletions stl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ set(HEADERS
${CMAKE_CURRENT_LIST_DIR}/inc/any
${CMAKE_CURRENT_LIST_DIR}/inc/array
${CMAKE_CURRENT_LIST_DIR}/inc/atomic
${CMAKE_CURRENT_LIST_DIR}/inc/barrier
${CMAKE_CURRENT_LIST_DIR}/inc/bit
${CMAKE_CURRENT_LIST_DIR}/inc/bitset
${CMAKE_CURRENT_LIST_DIR}/inc/cassert
Expand Down Expand Up @@ -153,6 +154,7 @@ set(HEADERS
${CMAKE_CURRENT_LIST_DIR}/inc/iso646.h
${CMAKE_CURRENT_LIST_DIR}/inc/istream
${CMAKE_CURRENT_LIST_DIR}/inc/iterator
${CMAKE_CURRENT_LIST_DIR}/inc/latch
${CMAKE_CURRENT_LIST_DIR}/inc/limits
${CMAKE_CURRENT_LIST_DIR}/inc/list
${CMAKE_CURRENT_LIST_DIR}/inc/locale
Expand All @@ -171,6 +173,7 @@ set(HEADERS
${CMAKE_CURRENT_LIST_DIR}/inc/ratio
${CMAKE_CURRENT_LIST_DIR}/inc/regex
${CMAKE_CURRENT_LIST_DIR}/inc/scoped_allocator
${CMAKE_CURRENT_LIST_DIR}/inc/semaphore
${CMAKE_CURRENT_LIST_DIR}/inc/set
${CMAKE_CURRENT_LIST_DIR}/inc/shared_mutex
${CMAKE_CURRENT_LIST_DIR}/inc/span
Expand Down
3 changes: 3 additions & 0 deletions stl/inc/__msvc_all_public_headers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@

#ifndef _M_CEE_PURE
#include <atomic>
#include <barrier>
#include <latch>
#include <semaphore>
#endif // _M_CEE_PURE

#ifndef _M_CEE
Expand Down
243 changes: 195 additions & 48 deletions stl/inc/algorithm
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,24 @@ namespace ranges {
}
}

template <forward_range _Rng>
_NODISCARD constexpr auto _Get_final_iterator_unwrapped(_Rng& _Range, const _Unwrapped_t<iterator_t<_Rng>>& _Mid) {
// find the (unwrapped) iterator in _Range which equals _Uend(_Range) [possibly O(N)]
// Pre: [ranges::begin(_Range), _Mid) and [_Mid, ranges::end(_Range)) denote ranges
if constexpr (common_range<_Rng>) {
return _Uend(_Range);
} else if constexpr (sized_range<_Rng>) {
const auto _Dist = _RANGES distance(_Range);
if constexpr (sized_sentinel_for<_Unwrapped_t<iterator_t<_Rng>>, _Unwrapped_t<iterator_t<_Rng>>>) {
return _RANGES next(_Mid, _Dist - (_Mid - _Ubegin(_Range)));
} else {
return _RANGES next(_Ubegin(_Range), _Dist);
}
} else {
return _RANGES next(_Mid, _Uend(_Range));
}
}

#ifdef __clang__
#pragma clang diagnostic pop
#endif // __clang__
Expand Down Expand Up @@ -459,52 +477,6 @@ template <class _ExPo, class _FwdIt, class _Pr, _Enable_if_execution_policy_t<_E
_NODISCARD _FwdIt find_if(_ExPo&& _Exec, _FwdIt _First, const _FwdIt _Last, _Pr _Pred) noexcept; // terminates
#endif // _HAS_CXX17

#ifdef __cpp_lib_concepts
namespace ranges {
// VARIABLE ranges::find_if
// concept-constrained for strict enforcement as it is used by several algorithms
template <input_iterator _It, sentinel_for<_It> _Se, class _Pj, indirect_unary_predicate<projected<_It, _Pj>> _Pr>
_NODISCARD constexpr _It _Find_if_unchecked(_It _First, const _Se _Last, _Pr _Pred, _Pj _Proj) {
for (; _First != _Last; ++_First) {
if (_STD invoke(_Pred, _STD invoke(_Proj, *_First))) {
break;
}
}

return _First;
}

class _Find_if_fn : private _Not_quite_object {
public:
using _Not_quite_object::_Not_quite_object;

template <input_iterator _It, sentinel_for<_It> _Se, class _Pj = identity,
indirect_unary_predicate<projected<_It, _Pj>> _Pr>
_NODISCARD constexpr _It operator()(_It _First, _Se _Last, _Pr _Pred, _Pj _Proj = {}) const {
_Adl_verify_range(_First, _Last);
auto _UResult = _RANGES _Find_if_unchecked(
_Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Last)), _Pass_fn(_Pred), _Pass_fn(_Proj));

_Seek_wrapped(_First, _STD move(_UResult));
return _First;
}

template <input_range _Rng, class _Pj = identity,
indirect_unary_predicate<projected<iterator_t<_Rng>, _Pj>> _Pr>
_NODISCARD constexpr borrowed_iterator_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred, _Pj _Proj = {}) const {
auto _First = _RANGES begin(_Range);
auto _UResult = _RANGES _Find_if_unchecked(
_Get_unwrapped(_STD move(_First)), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj));

_Seek_wrapped(_First, _STD move(_UResult));
return _First;
}
};

inline constexpr _Find_if_fn find_if{_Not_quite_object::_Construct_tag{}};
} // namespace ranges
#endif // __cpp_lib_concepts

// FUNCTION TEMPLATE find_if_not
template <class _InIt, class _Pr>
_NODISCARD _CONSTEXPR20 _InIt find_if_not(_InIt _First, const _InIt _Last, _Pr _Pred) {
Expand Down Expand Up @@ -3972,7 +3944,7 @@ namespace ranges {
#endif // __cpp_lib_is_constant_evaluated
{
const auto _Distance = static_cast<size_t>(_ULast - _UFirst);
_CSTD memset(_UFirst, static_cast<unsigned char>(_Value), _Distance);
_Fill_memset(_UFirst, _Value, _Distance);
_UFirst += _Distance;
_Seek_wrapped(_First, _UFirst);
return _First;
Expand Down Expand Up @@ -4011,7 +3983,7 @@ namespace ranges {
if (!_STD is_constant_evaluated())
#endif // __cpp_lib_is_constant_evaluated
{
_CSTD memset(_UFirst, static_cast<unsigned char>(_Value), static_cast<size_t>(_Count));
_Fill_memset(_UFirst, _Value, static_cast<size_t>(_Count));
_UFirst += _Count;
_Seek_wrapped(_First, _UFirst); // no need to move since _UFirst is a pointer
return _First;
Expand Down Expand Up @@ -8077,6 +8049,85 @@ void partial_sort(_ExPo&&, _RanIt _First, _RanIt _Mid, _RanIt _Last) noexcept /*
// parallelism suspected to be infeasible
return _STD partial_sort(_First, _Mid, _Last);
}

#ifdef __cpp_lib_concepts
namespace ranges {
// VARIABLE ranges::partial_sort
class _Partial_sort_fn : private _Not_quite_object {
public:
using _Not_quite_object::_Not_quite_object;

// clang-format off
template <random_access_iterator _It, sentinel_for<_It> _Se, class _Pr = ranges::less, class _Pj = identity>
requires sortable<_It, _Pr, _Pj>
constexpr _It operator()(_It _First, _It _Mid, _Se _Last, _Pr _Pred = {}, _Pj _Proj = {}) const {
// clang-format on
_Adl_verify_range(_First, _Mid);
_Adl_verify_range(_Mid, _Last);

if constexpr (is_same_v<_It, _Se>) {
_Partial_sort_common(_Get_unwrapped(_STD move(_First)), _Get_unwrapped(_STD move(_Mid)),
_Get_unwrapped(_Last), _Pass_fn(_Pred), _Pass_fn(_Proj));
return _Last;
} else {
auto _UMid = _Get_unwrapped(_STD move(_Mid));
auto _ULast = _Get_final_iterator_unwrapped<_It>(_UMid, _STD move(_Last));
_Seek_wrapped(_Mid, _ULast);
_Partial_sort_common(_Get_unwrapped(_STD move(_First)), _STD move(_UMid), _STD move(_ULast),
_Pass_fn(_Pred), _Pass_fn(_Proj));
return _Mid;
}
}

// clang-format off
template <random_access_range _Rng, class _Pr = ranges::less, class _Pj = identity>
requires sortable<iterator_t<_Rng>, _Pr, _Pj>
constexpr borrowed_iterator_t<_Rng> operator()(
_Rng&& _Range, iterator_t<_Rng> _Mid, _Pr _Pred = {}, _Pj _Proj = {}) const {
// clang-format on
_Adl_verify_range(_RANGES begin(_Range), _Mid);
_Adl_verify_range(_Mid, _RANGES end(_Range));

if constexpr (common_range<_Rng>) {
_Partial_sort_common(
_Ubegin(_Range), _Get_unwrapped(_STD move(_Mid)), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj));
return _RANGES end(_Range);
} else {
auto _UMid = _Get_unwrapped(_STD move(_Mid));
auto _ULast = _Get_final_iterator_unwrapped(_Range, _UMid);
_Seek_wrapped(_Mid, _ULast);
_Partial_sort_common(
_Ubegin(_Range), _STD move(_UMid), _STD move(_ULast), _Pass_fn(_Pred), _Pass_fn(_Proj));
return _Mid;
}
}

private:
template <class _It, class _Pr, class _Pj>
static constexpr void _Partial_sort_common(_It _First, _It _Mid, const _It _Last, _Pr _Pred, _Pj _Proj) {
_STL_INTERNAL_STATIC_ASSERT(random_access_iterator<_It>);
_STL_INTERNAL_STATIC_ASSERT(sortable<_It, _Pr, _Pj>);

if (_First == _Mid) {
return; // nothing to do
}

_Make_heap_common(_First, _Mid, _Pred, _Proj);
for (auto _Next = _Mid; _Next != _Last; ++_Next) {
if (_STD invoke(_Pred, _STD invoke(_Proj, *_Next), _STD invoke(_Proj, *_First))) {
// replace top with new largest
iter_value_t<_It> _Val = _RANGES iter_move(_Next);
_RANGES _Pop_heap_hole_unchecked(_First, _Mid, _Next, _STD move(_Val), _Pred, _Proj, _Proj);
}
}

_Sort_heap_common(_STD move(_First), _STD move(_Mid), _Pred, _Proj);
}
};

inline constexpr _Partial_sort_fn partial_sort{_Not_quite_object::_Construct_tag{}};
} // namespace ranges
#endif // __cpp_lib_concepts
#endif // _HAS_CXX17

// FUNCTION TEMPLATE partial_sort_copy
Expand Down Expand Up @@ -8136,6 +8187,102 @@ _RanIt partial_sort_copy(_ExPo&&, _FwdIt _First1, _FwdIt _Last1, _RanIt _First2,
_REQUIRE_PARALLEL_ITERATOR(_FwdIt);
return _STD partial_sort_copy(_First1, _Last1, _First2, _Last2);
}

#ifdef __cpp_lib_concepts
namespace ranges {
// ALIAS TEMPLATE partial_sort_copy_result
template <class _In, class _Out>
using partial_sort_copy_result = in_out_result<_In, _Out>;

// VARIABLE ranges::partial_sort_copy
class _Partial_sort_copy_fn : private _Not_quite_object {
public:
using _Not_quite_object::_Not_quite_object;

// clang-format off
template <input_iterator _It1, sentinel_for<_It1> _Se1, random_access_iterator _It2, sentinel_for<_It2> _Se2,
class _Pr = ranges::less, class _Pj1 = identity, class _Pj2 = identity>
requires indirectly_copyable<_It1, _It2>
&& sortable<_It2, _Pr, _Pj2>
&& indirect_strict_weak_order<_Pr, projected<_It1, _Pj1>, projected<_It2, _Pj2>>
constexpr partial_sort_copy_result<_It1, _It2> operator()(_It1 _First1, _Se1 _Last1, _It2 _First2, _Se2 _Last2,
_Pr _Pred = {}, _Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const {
// clang-format on
_Adl_verify_range(_First1, _Last1);
_Adl_verify_range(_First2, _Last2);

auto _UResult = _Partial_sort_copy_unchecked(_Get_unwrapped(_STD move(_First1)),
_Get_unwrapped(_STD move(_Last1)), _Get_unwrapped(_STD move(_First2)),
_Get_unwrapped(_STD move(_Last2)), _Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2));

_Seek_wrapped(_First1, _STD move(_UResult.in));
_Seek_wrapped(_First2, _STD move(_UResult.out));
return {_STD move(_First1), _STD move(_First2)};
}

// clang-format off
template <input_range _Rng1, random_access_range _Rng2, class _Pr = ranges::less, class _Pj1 = identity,
class _Pj2 = identity>
requires indirectly_copyable<iterator_t<_Rng1>, iterator_t<_Rng2>>
&& sortable<iterator_t<_Rng2>, _Pr, _Pj2>
&& indirect_strict_weak_order<_Pr, projected<iterator_t<_Rng1>, _Pj1>,
projected<iterator_t<_Rng2>, _Pj2>>
constexpr partial_sort_copy_result<borrowed_iterator_t<_Rng1>, borrowed_iterator_t<_Rng2>> operator()(
_Rng1&& _Range1, _Rng2&& _Range2, _Pr _Pred = {}, _Pj1 _Proj1 = {}, _Pj2 _Proj2 = {}) const {
// clang-format on
auto _First = _RANGES begin(_Range1);
auto _UResult = _Partial_sort_copy_unchecked(_Get_unwrapped(_STD move(_First)), _Uend(_Range1),
_Ubegin(_Range2), _Uend(_Range2), _Pass_fn(_Pred), _Pass_fn(_Proj1), _Pass_fn(_Proj2));

_Seek_wrapped(_First, _STD move(_UResult.in));
return {_STD move(_First), _Rewrap_iterator(_Range2, _STD move(_UResult.out))};
}

private:
template <class _It1, class _Se1, class _It2, class _Se2, class _Pr, class _Pj1, class _Pj2>
_NODISCARD static constexpr partial_sort_copy_result<_It1, _It2> _Partial_sort_copy_unchecked(
_It1 _First1, _Se1 _Last1, _It2 _First2, const _Se2 _Last2, _Pr _Pred, _Pj1 _Proj1, _Pj2 _Proj2) {
_STL_INTERNAL_STATIC_ASSERT(input_iterator<_It1>);
_STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se1, _It1>);
_STL_INTERNAL_STATIC_ASSERT(random_access_iterator<_It2>);
_STL_INTERNAL_STATIC_ASSERT(sentinel_for<_Se2, _It2>);
_STL_INTERNAL_STATIC_ASSERT(indirectly_copyable<_It1, _It2>);
_STL_INTERNAL_STATIC_ASSERT(sortable<_It2, _Pr, _Pj2>);
_STL_INTERNAL_STATIC_ASSERT(indirect_strict_weak_order<_Pr, projected<_It1, _Pj1>, projected<_It2, _Pj2>>);

if (_First1 == _Last1 || _First2 == _Last2) {
_RANGES advance(_First1, _STD move(_Last1));
return {_STD move(_First1), _STD move(_First2)};
}

// copy N = min(distance(_First1, _Last1), distance(_First2, _Last2)) elements
auto _Mid2 = _First2;
do {
*_Mid2 = *_First1;
++_First1;
++_Mid2;
} while (_First1 != _Last1 && _Mid2 != _Last2);

_Make_heap_common(_First2, _Mid2, _Pred, _Proj2); // Make a heap
for (; _First1 != _Last1; ++_First1) { // Scan the remaining elements...
// ... for values less than the largest in the heap ...
if (_STD invoke(_Pred, _STD invoke(_Proj1, *_First1), _STD invoke(_Proj2, *_First2))) {
// ... to replace the largest, after which we restore the heap invariants.
using _Diff = iter_difference_t<_It2>;
_RANGES _Pop_heap_hole_by_index(_First2, static_cast<_Diff>(0), static_cast<_Diff>(_Mid2 - _First2),
*_First1, _Pred, _Proj2, _Proj1);
}
}

// the heap contains the N smallest elements; sort them
_Sort_heap_common(_STD move(_First2), _Mid2, _Pred, _Proj2);
return {_STD move(_First1), _STD move(_Mid2)};
}
};

inline constexpr _Partial_sort_copy_fn partial_sort_copy{_Not_quite_object::_Construct_tag{}};
} // namespace ranges
#endif // __cpp_lib_concepts
#endif // _HAS_CXX17

// FUNCTION TEMPLATE nth_element
Expand Down
Loading