Skip to content

Commit d9caea1

Browse files
author
Xiaoyang Liu
authored
[libc++][ranges] LWG3564: transform_view::iterator<true>::value_type and iterator_category should use const F& (#91816)
## Introduction This patch implements LWG3564: `transform_view::iterator<true>::value_type` and `iterator_category` should use `const F&`. `transform_view`'s iterator currently obtained from a `const transform_view` invoke the transformation function as `const`, but the `value_type` and `iterator_category` determination uses non-`const` `F&`. ## Reference - [[range.transform.iterator]](https://eel.is/c++draft/range.transform.iterator) - [LWG3564](https://cplusplus.github.io/LWG/issue3564)
1 parent fe7d284 commit d9caea1

File tree

4 files changed

+25
-3
lines changed

4 files changed

+25
-3
lines changed

libcxx/docs/Status/Cxx23Issues.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@
159159
"`LWG3660 <https://wg21.link/LWG3660>`__","``iterator_traits<common_iterator>::pointer`` should conform to §[iterator.traits]","February 2022","|Complete|","14.0","|ranges|"
160160
"`LWG3661 <https://wg21.link/LWG3661>`__","``constinit atomic<shared_ptr<T>> a(nullptr);`` should work","February 2022","","",""
161161
"","","","","",""
162-
"`LWG3564 <https://wg21.link/LWG3564>`__","``transform_view::iterator<true>::value_type`` and ``iterator_category`` should use ``const F&``","July 2022","","","|ranges|"
162+
"`LWG3564 <https://wg21.link/LWG3564>`__","``transform_view::iterator<true>::value_type`` and ``iterator_category`` should use ``const F&``","July 2022","|Complete|","20.0","|ranges|"
163163
"`LWG3617 <https://wg21.link/LWG3617>`__","``function``/``packaged_task`` deduction guides and deducing ``this``","July 2022","","",""
164164
"`LWG3656 <https://wg21.link/LWG3656>`__","Inconsistent bit operations returning a count","July 2022","|Complete|","15.0",""
165165
"`LWG3659 <https://wg21.link/LWG3659>`__","Consider ``ATOMIC_FLAG_INIT`` undeprecation","July 2022","|Complete|","15.0",""

libcxx/include/__ranges/transform_view.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,8 @@ template <input_range _View, copy_constructible _Fn>
173173
# endif
174174
requires __transform_view_constraints<_View, _Fn>
175175
template <bool _Const>
176-
class transform_view<_View, _Fn>::__iterator : public __transform_view_iterator_category_base<_View, _Fn> {
176+
class transform_view<_View, _Fn>::__iterator
177+
: public __transform_view_iterator_category_base<_View, __maybe_const<_Const, _Fn>> {
177178

178179
using _Parent = __maybe_const<_Const, transform_view>;
179180
using _Base = __maybe_const<_Const, _View>;
@@ -190,7 +191,7 @@ class transform_view<_View, _Fn>::__iterator : public __transform_view_iterator_
190191
iterator_t<_Base> __current_ = iterator_t<_Base>();
191192

192193
using iterator_concept = typename __transform_view_iterator_concept<_View>::type;
193-
using value_type = remove_cvref_t<invoke_result_t<_Fn&, range_reference_t<_Base>>>;
194+
using value_type = remove_cvref_t<invoke_result_t<__maybe_const<_Const, _Fn>&, range_reference_t<_Base>>>;
194195
using difference_type = range_difference_t<_Base>;
195196

196197
_LIBCPP_HIDE_FROM_ABI __iterator()

libcxx/test/std/ranges/range.adaptors/range.transform/iterator/types.pass.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,22 @@ constexpr bool test() {
6161
static_assert(std::same_as<typename TIter::value_type, int>);
6262
static_assert(std::same_as<typename TIter::difference_type, std::ptrdiff_t>);
6363
}
64+
{
65+
// Member typedefs for random access iterator, LWG3564 mutable overload
66+
using TView = std::ranges::transform_view<RandomAccessView, PlusOneMutableOverload>;
67+
using TIter = std::ranges::iterator_t<TView>;
68+
static_assert(std::same_as<typename TIter::iterator_concept, std::random_access_iterator_tag>);
69+
static_assert(std::same_as<typename TIter::iterator_category, std::random_access_iterator_tag>);
70+
static_assert(std::same_as<typename TIter::value_type, int>);
71+
static_assert(std::same_as<typename TIter::difference_type, std::ptrdiff_t>);
72+
73+
using CTIter = std::ranges::iterator_t<const TView>;
74+
static_assert(std::same_as<typename CTIter::iterator_concept, std::random_access_iterator_tag>);
75+
static_assert(std::same_as<typename CTIter::iterator_category,
76+
std::input_iterator_tag>); // Note: this is now input_iterator_tag.
77+
static_assert(std::same_as<typename CTIter::value_type, int>);
78+
static_assert(std::same_as<typename CTIter::difference_type, std::ptrdiff_t>);
79+
}
6480
{
6581
// Member typedefs for bidirectional iterator.
6682
using TView = std::ranges::transform_view<BidirectionalView, Increment>;

libcxx/test/std/ranges/range.adaptors/range.transform/types.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,11 @@ struct PlusOne {
131131
constexpr int operator()(int x) const { return x + 1; }
132132
};
133133

134+
struct PlusOneMutableOverload {
135+
constexpr int operator()(int x) const { return x + 1; }
136+
constexpr int& operator()(int& x) { return ++x; }
137+
};
138+
134139
struct Increment {
135140
constexpr int& operator()(int& x) { return ++x; }
136141
};

0 commit comments

Comments
 (0)