Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ADL-proof implementation of algorithms in [alg.nonmodifying] #4138

Merged
570 changes: 290 additions & 280 deletions stl/inc/algorithm

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions stl/inc/atomic
Original file line number Diff line number Diff line change
Expand Up @@ -1109,7 +1109,7 @@ struct _Atomic_storage<_Ty, 8> { // lock-free using 8-byte intrinsics
}

_NODISCARD _TVal load(const memory_order _Order) const noexcept { // load with given memory order
const auto _Mem = _Atomic_address_as<long long>(_Storage);
const auto _Mem = _STD _Atomic_address_as<long long>(_Storage);
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
long long _As_bytes;
#if _STD_ATOMIC_USE_ARM64_LDAR_STLR == 1
_ATOMIC_LOAD_ARM64(_As_bytes, 64, _Mem, static_cast<unsigned int>(_Order))
Expand Down Expand Up @@ -1147,17 +1147,17 @@ struct _Atomic_storage<_Ty, 8> { // lock-free using 8-byte intrinsics

bool compare_exchange_strong(_TVal& _Expected, const _TVal _Desired,
const memory_order _Order = memory_order_seq_cst) noexcept { // CAS with given memory order
long long _Expected_bytes = _Atomic_reinterpret_as<long long>(_Expected); // read before atomic operation
long long _Expected_bytes = _STD _Atomic_reinterpret_as<long long>(_Expected); // read before atomic operation
long long _Prev_bytes;

#if _CMPXCHG_MASK_OUT_PADDING_BITS
if constexpr (_Might_have_non_value_bits<_TVal>) {
_Storage_for<_TVal> _Mask{_Form_mask};
const long long _Mask_val = _Atomic_reinterpret_as<long long>(_Mask);
const long long _Mask_val = _STD _Atomic_reinterpret_as<long long>(_Mask);

for (;;) {
_ATOMIC_CHOOSE_INTRINSIC(static_cast<unsigned int>(_Order), _Prev_bytes, _InterlockedCompareExchange64,
_Atomic_address_as<long long>(_Storage), _Atomic_reinterpret_as<long long>(_Desired),
_STD _Atomic_address_as<long long>(_Storage), _STD _Atomic_reinterpret_as<long long>(_Desired),
_Expected_bytes);
if (_Prev_bytes == _Expected_bytes) {
return true;
Expand All @@ -1172,7 +1172,8 @@ struct _Atomic_storage<_Ty, 8> { // lock-free using 8-byte intrinsics
}
#endif // _CMPXCHG_MASK_OUT_PADDING_BITS
_ATOMIC_CHOOSE_INTRINSIC(static_cast<unsigned int>(_Order), _Prev_bytes, _InterlockedCompareExchange64,
_Atomic_address_as<long long>(_Storage), _Atomic_reinterpret_as<long long>(_Desired), _Expected_bytes);
_STD _Atomic_address_as<long long>(_Storage), _STD _Atomic_reinterpret_as<long long>(_Desired),
_Expected_bytes);
if (_Prev_bytes == _Expected_bytes) {
return true;
}
Expand Down
363 changes: 183 additions & 180 deletions stl/inc/execution

Large diffs are not rendered by default.

288 changes: 148 additions & 140 deletions stl/inc/xutility

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ tests\GH_001277_num_get_bad_grouping
tests\GH_001411_core_headers
tests\GH_001530_binomial_accuracy
tests\GH_001541_case_sensitive_boolalpha
tests\GH_001596_adl_proof_algorithms
tests\GH_001638_dllexport_derived_classes
tests\GH_001850_clog_tied_to_cout
tests\GH_001858_iostream_exception
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/GH_001596_adl_proof_algorithms/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_matrix.lst
236 changes: 236 additions & 0 deletions tests/std/tests/GH_001596_adl_proof_algorithms/test.compile.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <algorithm>
#include <cstddef>
#if _HAS_CXX17
#include <execution>
#endif // _HAS_CXX17
#include <type_traits>
#include <utility>

template <class Tag>
struct tagged_truth {
template <class T>
constexpr bool operator()(T&&) const noexcept {
return true;
}
};

template <class Tag>
struct tagged_equal {
template <class T, class U>
constexpr auto operator()(T&& t, U&& u) const -> decltype(std::forward<T>(t) == std::forward<U>(u)) {
return std::forward<T>(t) == std::forward<U>(u);
}
};

template <class T>
struct holder {
T t;
};

#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395
template <class Tag>
struct tagged_left_selector {
template <class T>
constexpr T operator()(T lhs, T) const noexcept {
return lhs;
}
};
#endif // _HAS_CXX23 && defined(__cpp_lib_concepts)

struct incomplete;

using simple_truth = tagged_truth<void>;

using validator = holder<incomplete>*;
using validating_truth = tagged_truth<holder<incomplete>>;
using validating_equal = tagged_equal<holder<incomplete>>;

#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395
using simple_left_selector = tagged_left_selector<void>;

using validating_left_selector = tagged_left_selector<holder<incomplete>>;
#endif // _HAS_CXX23 && defined(__cpp_lib_concepts)

void test_algorithms() {
int iarr[1]{};
validator varr[1]{};

(void) std::all_of(varr, varr, simple_truth{});
(void) std::all_of(iarr, iarr, validating_truth{});

(void) std::any_of(varr, varr, simple_truth{});
(void) std::any_of(iarr, iarr, validating_truth{});

(void) std::none_of(varr, varr, simple_truth{});
(void) std::none_of(iarr, iarr, validating_truth{});

(void) std::for_each(varr, varr, simple_truth{});
(void) std::for_each(varr, varr, validating_truth{});
(void) std::for_each(iarr, iarr, validating_truth{});

#if _HAS_CXX17
(void) std::for_each_n(varr, 0, simple_truth{});
(void) std::for_each_n(varr, 0, validating_truth{});
(void) std::for_each_n(iarr, 0, validating_truth{});
#endif // _HAS_CXX17

(void) std::find(varr, varr, validator{});

(void) std::find_if(varr, varr, simple_truth{});
(void) std::find_if(iarr, iarr, validating_truth{});

(void) std::find_if_not(varr, varr, simple_truth{});
(void) std::find_if_not(iarr, iarr, validating_truth{});

(void) std::find_end(varr, varr, varr, varr);
(void) std::find_end(varr, varr, varr, varr, validating_equal{});
(void) std::find_end(iarr, iarr, iarr, iarr, validating_equal{});

(void) std::find_first_of(varr, varr, varr, varr);
(void) std::find_first_of(varr, varr, varr, varr, validating_equal{});
(void) std::find_first_of(iarr, iarr, iarr, iarr, validating_equal{});

(void) std::adjacent_find(varr, varr);
(void) std::adjacent_find(iarr, iarr, validating_equal{});

(void) std::count(varr, varr, validator{});

(void) std::count_if(varr, varr, simple_truth{});
(void) std::count_if(iarr, iarr, validating_truth{});

(void) std::mismatch(varr, varr, varr);
(void) std::mismatch(varr, varr, varr, varr);
(void) std::mismatch(iarr, iarr, iarr, validating_equal{});
(void) std::mismatch(iarr, iarr, iarr, iarr, validating_equal{});

(void) std::equal(varr, varr, varr);
(void) std::equal(varr, varr, varr, varr);
(void) std::equal(iarr, iarr, iarr, validating_equal{});
(void) std::equal(iarr, iarr, iarr, iarr, validating_equal{});

(void) std::is_permutation(varr, varr, varr);
(void) std::is_permutation(varr, varr, varr, validating_equal{});
(void) std::is_permutation(varr, varr, varr, varr);
(void) std::is_permutation(varr, varr, varr, varr, validating_equal{});
(void) std::is_permutation(iarr, iarr, iarr, validating_equal{});
(void) std::is_permutation(iarr, iarr, iarr, iarr, validating_equal{});

(void) std::search(varr, varr, varr, varr);
(void) std::search(iarr, iarr, iarr, iarr, validating_equal{});
}

#if _HAS_CXX17
template <auto& ExecutionPolicy>
void test_per_execution_policy() {
int iarr[1]{};
validator varr[1]{};

(void) std::all_of(ExecutionPolicy, varr, varr, simple_truth{});
(void) std::all_of(ExecutionPolicy, iarr, iarr, validating_truth{});

(void) std::any_of(ExecutionPolicy, varr, varr, simple_truth{});
(void) std::any_of(ExecutionPolicy, iarr, iarr, validating_truth{});

(void) std::none_of(ExecutionPolicy, varr, varr, simple_truth{});
(void) std::none_of(ExecutionPolicy, iarr, iarr, validating_truth{});

std::for_each(ExecutionPolicy, varr, varr, simple_truth{});
std::for_each(ExecutionPolicy, varr, varr, validating_truth{});
std::for_each(ExecutionPolicy, iarr, iarr, validating_truth{});

(void) std::for_each_n(ExecutionPolicy, varr, 0, simple_truth{});
(void) std::for_each_n(ExecutionPolicy, varr, 0, validating_truth{});
(void) std::for_each_n(ExecutionPolicy, iarr, 0, validating_truth{});

(void) std::find(ExecutionPolicy, varr, varr, validator{});

(void) std::find_if(ExecutionPolicy, varr, varr, simple_truth{});
(void) std::find_if(ExecutionPolicy, iarr, iarr, validating_truth{});

(void) std::find_if_not(ExecutionPolicy, varr, varr, simple_truth{});
(void) std::find_if_not(ExecutionPolicy, iarr, iarr, validating_truth{});

(void) std::find_end(ExecutionPolicy, varr, varr, varr, varr);
(void) std::find_end(ExecutionPolicy, varr, varr, varr, varr, validating_equal{});
(void) std::find_end(ExecutionPolicy, iarr, iarr, iarr, iarr, validating_equal{});

(void) std::find_first_of(ExecutionPolicy, varr, varr, varr, varr);
(void) std::find_first_of(ExecutionPolicy, varr, varr, varr, varr, validating_equal{});
(void) std::find_first_of(ExecutionPolicy, iarr, iarr, iarr, iarr, validating_equal{});

(void) std::adjacent_find(ExecutionPolicy, varr, varr);
(void) std::adjacent_find(ExecutionPolicy, iarr, iarr, validating_equal{});

(void) std::count(ExecutionPolicy, varr, varr, validator{});

(void) std::count_if(ExecutionPolicy, varr, varr, simple_truth{});
(void) std::count_if(ExecutionPolicy, iarr, iarr, validating_truth{});

(void) std::mismatch(ExecutionPolicy, varr, varr, varr);
(void) std::mismatch(ExecutionPolicy, varr, varr, varr, varr);
(void) std::mismatch(ExecutionPolicy, iarr, iarr, iarr, validating_equal{});
(void) std::mismatch(ExecutionPolicy, iarr, iarr, iarr, iarr, validating_equal{});

(void) std::equal(ExecutionPolicy, varr, varr, varr);
(void) std::equal(ExecutionPolicy, varr, varr, varr, varr);
(void) std::equal(ExecutionPolicy, iarr, iarr, iarr, validating_equal{});
(void) std::equal(ExecutionPolicy, iarr, iarr, iarr, iarr, validating_equal{});

(void) std::search(ExecutionPolicy, varr, varr, varr, varr);
(void) std::search(ExecutionPolicy, iarr, iarr, iarr, iarr, validating_equal{});

(void) std::search_n(ExecutionPolicy, varr, varr, 0, validator{});
(void) std::search_n(ExecutionPolicy, iarr, iarr, 0, 0, validating_equal{});
}

void test_parallel_algorithms() {
test_per_execution_policy<std::execution::seq>();
test_per_execution_policy<std::execution::par>();
test_per_execution_policy<std::execution::par_unseq>();
#if _HAS_CXX20
test_per_execution_policy<std::execution::unseq>();
#endif // _HAS_CXX20
}
#endif // _HAS_CXX17

#if _HAS_CXX23 && defined(__cpp_lib_concepts) && !defined(_M_CEE) // TRANSITION, GH-395, VSO-1659496
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
void test_ranges_non_projected_algorithms() {
using namespace std::ranges;

int iarr[1]{};
validator varr[1]{};

(void) fold_left(varr, varr, validator{}, simple_left_selector{});
(void) fold_left(varr, validator{}, simple_left_selector{});
(void) fold_left(iarr, iarr, 0, validating_left_selector{});
(void) fold_left(iarr, 0, validating_left_selector{});

(void) fold_left_first(varr, varr + 1, simple_left_selector{});
(void) fold_left_first(varr, simple_left_selector{});
(void) fold_left_first(iarr, iarr + 1, validating_left_selector{});
(void) fold_left_first(iarr, validating_left_selector{});

(void) fold_right(varr, varr, validator{}, simple_left_selector{});
(void) fold_right(varr, validator{}, simple_left_selector{});
(void) fold_right(iarr, iarr, 0, validating_left_selector{});
(void) fold_right(iarr, 0, validating_left_selector{});

(void) fold_right_last(varr, varr + 1, simple_left_selector{});
(void) fold_right_last(varr, simple_left_selector{});
(void) fold_right_last(iarr, iarr + 1, validating_left_selector{});
(void) fold_right_last(iarr, validating_left_selector{});

(void) fold_left_with_iter(varr, varr, validator{}, simple_left_selector{});
(void) fold_left_with_iter(varr, validator{}, simple_left_selector{});
(void) fold_left_with_iter(iarr, iarr, 0, validating_left_selector{});
(void) fold_left_with_iter(iarr, 0, validating_left_selector{});

(void) fold_left_first_with_iter(varr, varr, simple_left_selector{});
(void) fold_left_first_with_iter(varr, simple_left_selector{});
(void) fold_left_first_with_iter(iarr, iarr, validating_left_selector{});
(void) fold_left_first_with_iter(iarr, validating_left_selector{});
}
#endif // _HAS_CXX23 && defined(__cpp_lib_concepts) && !defined(_M_CEE)
Loading
Loading