static auto
_S_iter_cat()
{
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3564. transform_view::iterator<true>::value_type and
+ // iterator_category should use const F&
using _Base = transform_view::_Base<_Const>;
- using _Res = invoke_result_t<_Fp&, range_reference_t<_Base>>;
+ using _Res = invoke_result_t<__maybe_const_t<_Const, _Fp>&,
+ range_reference_t<_Base>>;
if constexpr (is_lvalue_reference_v<_Res>)
{
using _Cat
using iterator_concept = decltype(_S_iter_concept());
// iterator_category defined in __transform_view_iter_cat
using value_type
- = remove_cvref_t<invoke_result_t<_Fp&, range_reference_t<_Base>>>;
+ = remove_cvref_t<invoke_result_t<__maybe_const_t<_Const, _Fp>&,
+ range_reference_t<_Base>>>;
using difference_type = range_difference_t<_Base>;
_Iterator() requires default_initializable<_Base_iter> = default;
#endif
}
+void
+test10()
+{
+ struct F {
+ short operator()(int) { return 0; }
+ const int& operator()(const int& i) const { return i; }
+ };
+
+ int x[] {2, 4};
+ const auto xform = x | views::transform(F{});
+ using const_iterator = decltype(xform.begin());
+ // LWG 3564. transform_view::iterator<true>::value_type and iterator_category
+ // should use const F&
+ static_assert(std::same_as<std::iter_value_t<const_iterator>, int>);
+ using cat = std::iterator_traits<const_iterator>::iterator_category;
+ static_assert(std::same_as<cat, std::random_access_iterator_tag>);
+}
+
int
main()
{
test07();
test08();
test09();
+ test10();
}