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

Implement P2538R1 ADL-Proof projected #3822

Merged
merged 7 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
40 changes: 29 additions & 11 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -864,22 +864,40 @@ _EXPORT_STD template <class _Fn, class... _Its>
requires (indirectly_readable<_Its> && ...) && invocable<_Fn, iter_reference_t<_Its>...>
using indirect_result_t = invoke_result_t<_Fn, iter_reference_t<_Its>...>;

_EXPORT_STD template <indirectly_readable _It, indirectly_regular_unary_invocable<_It> _Proj>
struct projected {
using value_type = remove_cvref_t<indirect_result_t<_Proj&, _It>>;
indirect_result_t<_Proj&, _It> operator*() const {
_CSTD abort();
}
template <class _It>
struct _Projected_difference_type_impl {
struct _Base {};
};

template <weakly_incrementable _It>
struct _Projected_difference_type_impl<_It> {
struct _Base {
using difference_type = iter_difference_t<_It>;
};
};

template <class _It, class _Proj>
struct _Indirect_value_impl<projected<_It, _Proj>> {
using type = invoke_result_t<_Proj&, _Indirect_value_t<_It>>;
struct _Projected_impl {
struct _Type : _Projected_difference_type_impl<_It>::_Base {
using _Iterator = _It;
using _Projection = _Proj;

using value_type = remove_cvref_t<indirect_result_t<_Proj&, _It>>;
indirect_result_t<_Proj&, _It> operator*() const {
_CSTD abort();
}
};
};

template <weakly_incrementable _It, class _Proj>
struct incrementable_traits<projected<_It, _Proj>> {
using difference_type = iter_difference_t<_It>;
_EXPORT_STD template <indirectly_readable _It, indirectly_regular_unary_invocable<_It> _Proj>
using projected = _Projected_impl<_It, _Proj>::_Type;

template <class _Ty>
concept _Projected_specialization = same_as<_Ty, projected<typename _Ty::_Iterator, typename _Ty::_Projection>>;

template <_Projected_specialization _ProjTy>
struct _Indirect_value_impl<_ProjTy> {
using type = invoke_result_t<typename _ProjTy::_Projection&, _Indirect_value_t<typename _ProjTy::_Iterator>>;
};

_EXPORT_STD template <class _In, class _Out>
Expand Down
1 change: 1 addition & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@
// P2432R1 Fix istream_view
// P2508R1 basic_format_string, format_string, wformat_string
// P2520R0 move_iterator<T*> Should Be A Random-Access Iterator
// P2538R1 ADL-Proof projected
// P2572R1 std::format Fill Character Allowances
// P2588R3 barrier's Phase Completion Guarantees
// P2602R2 Poison Pills Are Too Toxic
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,7 @@ tests\P2474R2_views_repeat_death
tests\P2494R2_move_only_range_adaptors
tests\P2505R5_monadic_functions_for_std_expected
tests\P2517R1_apply_conditional_noexcept
tests\P2538R1_adl_proof_std_projected
tests\P2609R3_relaxing_ranges_just_a_smidge
tests\VSO_0000000_allocator_propagation
tests\VSO_0000000_any_calling_conventions
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P2538R1_adl_proof_std_projected/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 ..\concepts_20_matrix.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef _M_CEE // TRANSITION, VSO-1659496
#include <cassert>
#include <functional>
#include <iterator>
#include <ranges>
#include <utility>

using namespace std;

// TRANSITION, GH-1596, should use ranges::count
struct my_count_fn {
template <input_iterator I, sentinel_for<I> S, class T, class Proj = identity>
requires indirect_binary_predicate<ranges::equal_to, projected<I, Proj>, const T*>
constexpr iter_difference_t<I> operator()(I first, S last, const T& value, Proj proj = {}) const {
iter_difference_t<I> counter = 0;
for (; first != last; ++first) {
if (std::invoke(proj, *first) == value) { // intentionally qualified to avoid ADL
++counter;
}
}
return counter;
}

template <ranges::input_range R, class T, class Proj = identity>
requires indirect_binary_predicate<ranges::equal_to, projected<ranges::iterator_t<R>, Proj>, const T*>
constexpr ranges::range_difference_t<R> operator()(R&& r, const T& value, Proj proj = {}) const {
return (*this)(ranges::begin(r), ranges::end(r), value, ref(proj));
}
};

inline constexpr my_count_fn my_count;

template <class T>
struct Holder {
T t;
};
struct Incomplete;

static_assert(equality_comparable<Holder<Incomplete>*>);
static_assert(indirectly_comparable<Holder<Incomplete>**, Holder<Incomplete>**, equal_to<>>);
static_assert(sortable<Holder<Incomplete>**>);

constexpr bool test() {
Holder<Incomplete>* a[10] = {};
assert(my_count(a, a + 10, nullptr) == 10);
assert(my_count(a, nullptr) == 10);
return true;
}

static_assert(test());
#endif // _M_CEE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\concepts_latest_matrix.lst
RUNALL_INCLUDE ..\concepts_20_matrix.lst