Skip to content

Commit

Permalink
Implement P2538R1 ADL-Proof projected (#3822)
Browse files Browse the repository at this point in the history
Co-authored-by: Stephan T. Lavavej <stl@microsoft.com>
  • Loading branch information
frederick-vs-ja and StephanTLavavej committed Jul 14, 2023
1 parent 90dcf26 commit cc6533a
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 12 deletions.
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

0 comments on commit cc6533a

Please sign in to comment.