зеркало из https://github.com/microsoft/STL.git
Implement LWG-3564: `transform_view::iterator<true>::value_type` and `iterator_category` should use `const F&` (#2961)
This commit is contained in:
Родитель
9ed0e6bd89
Коммит
3e046a483e
|
@ -1903,20 +1903,22 @@ namespace ranges {
|
|||
template <bool _Const>
|
||||
class _Sentinel;
|
||||
|
||||
template <class _Base>
|
||||
template <bool _Const>
|
||||
struct _Category_base {};
|
||||
|
||||
template <forward_range _Base>
|
||||
struct _Category_base<_Base> {
|
||||
using iterator_category =
|
||||
conditional_t<is_lvalue_reference_v<invoke_result_t<_Fn&, range_reference_t<_Base>>>,
|
||||
conditional_t<derived_from<_Iter_cat_t<iterator_t<_Base>>, contiguous_iterator_tag>,
|
||||
random_access_iterator_tag, _Iter_cat_t<iterator_t<_Base>>>,
|
||||
input_iterator_tag>;
|
||||
template <bool _Const>
|
||||
requires forward_range<_Maybe_const<_Const, _Vw>>
|
||||
struct _Category_base<_Const> {
|
||||
using _Base = _Maybe_const<_Const, _Vw>;
|
||||
using iterator_category = conditional_t<
|
||||
is_lvalue_reference_v<invoke_result_t<_Maybe_const<_Const, _Fn>&, range_reference_t<_Base>>>,
|
||||
conditional_t<derived_from<_Iter_cat_t<iterator_t<_Base>>, contiguous_iterator_tag>,
|
||||
random_access_iterator_tag, _Iter_cat_t<iterator_t<_Base>>>,
|
||||
input_iterator_tag>;
|
||||
};
|
||||
|
||||
template <bool _Const>
|
||||
class _Iterator : public _Category_base<_Maybe_const<_Const, _Vw>> {
|
||||
class _Iterator : public _Category_base<_Const> {
|
||||
private:
|
||||
template <bool>
|
||||
friend class _Iterator;
|
||||
|
@ -1946,8 +1948,8 @@ namespace ranges {
|
|||
using iterator_concept = conditional_t<random_access_range<_Base>, random_access_iterator_tag,
|
||||
conditional_t<bidirectional_range<_Base>, bidirectional_iterator_tag,
|
||||
conditional_t<forward_range<_Base>, forward_iterator_tag, input_iterator_tag>>>;
|
||||
using value_type = remove_cvref_t<invoke_result_t<_Fn&, range_reference_t<_Base>>>;
|
||||
using difference_type = range_difference_t<_Base>;
|
||||
using value_type = remove_cvref_t<invoke_result_t<_Maybe_const<_Const, _Fn>&, range_reference_t<_Base>>>;
|
||||
using difference_type = range_difference_t<_Base>;
|
||||
|
||||
// clang-format off
|
||||
_Iterator() requires default_initializable<iterator_t<_Base>> = default;
|
||||
|
|
|
@ -321,6 +321,50 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Test a function object whose const and non-const versions behave differently
|
||||
struct difference_teller {
|
||||
constexpr auto& operator()(auto&& x) noexcept {
|
||||
auto& ref = x;
|
||||
return ref;
|
||||
}
|
||||
|
||||
constexpr auto operator()(auto&& x) const noexcept {
|
||||
return type_identity<decltype(x)>{};
|
||||
}
|
||||
};
|
||||
|
||||
template <ranges::input_range Rng>
|
||||
constexpr void test_difference_on_const_functor(Rng&& rng) {
|
||||
using ranges::transform_view, ranges::input_range, ranges::forward_range, ranges::bidirectional_range,
|
||||
ranges::random_access_range, ranges::iterator_t, ranges::range_reference_t, ranges::range_value_t;
|
||||
|
||||
using V = views::all_t<Rng>;
|
||||
using TV = transform_view<V, difference_teller>;
|
||||
|
||||
auto r = forward<Rng>(rng) | views::transform(difference_teller{});
|
||||
STATIC_ASSERT(is_same_v<decltype(r), TV>);
|
||||
|
||||
STATIC_ASSERT(is_lvalue_reference_v<range_reference_t<TV>>);
|
||||
if constexpr (input_range<const TV>) {
|
||||
STATIC_ASSERT(is_object_v<range_reference_t<const TV>>);
|
||||
STATIC_ASSERT(!is_same_v<range_value_t<TV>, range_value_t<const TV>>);
|
||||
}
|
||||
|
||||
if constexpr (forward_range<V>) {
|
||||
using It = iterator_t<V>;
|
||||
using TVIt = iterator_t<TV>;
|
||||
using VItCat = typename iterator_traits<It>::iterator_category;
|
||||
using TVItCat = typename iterator_traits<TVIt>::iterator_category;
|
||||
STATIC_ASSERT(
|
||||
is_same_v<TVItCat, VItCat> //
|
||||
|| (is_same_v<TVItCat, random_access_iterator_tag> && is_same_v<VItCat, contiguous_iterator_tag>) );
|
||||
}
|
||||
|
||||
if constexpr (forward_range<const V>) {
|
||||
STATIC_ASSERT(is_same_v<typename iterator_traits<iterator_t<const TV>>::iterator_category, input_iterator_tag>);
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr int some_ints[] = {0, 1, 2, 3, 4, 5, 6, 7};
|
||||
static constexpr int transformed_ints[] = {8, 9, 10, 11, 12, 13, 14, 15};
|
||||
|
||||
|
@ -329,6 +373,9 @@ struct instantiator {
|
|||
static constexpr void call() {
|
||||
R r{some_ints};
|
||||
test_one(r, transformed_ints);
|
||||
|
||||
R r2{some_ints};
|
||||
test_difference_on_const_functor(r2);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче