I want to get the type of the iterator to the const-casted contents of the vector. I thought I can use decltype
for it.
Apparently it is not that simple.
#include <ranges>
#include <vector>
const int& cast_const(int& i) {
return i;
}
struct PoC {
std::vector<int> _m;
decltype(_m | std::views::transform(cast_const)) _const = _m | std::views::transform(cast_const);
using const_iterator = decltype(_const.begin());
[[nodiscard]] auto cbegin() const { return _const.begin(); }
using iterator = decltype(_m.begin());
[[nodiscard]] auto begin() { return _m.begin(); }
};
void test() {
PoC p;
PoC::const_iterator cit = p.cbegin(); // ERROR: error: conversion from ‘_Iterator<true>’ to non-scalar type ‘_Iterator<false>’ requested
PoC::iterator it = p.begin(); // Works, because no ranges.
}
I believe it boils down to the fact, that PoC::const_iterator
is of type std::ranges::transform_view<std::ranges::ref_view<std::vector<int> >, int& (*)(int&)>::_Iterator<false>
, while the return value of p.cbegin()
is of type std::ranges::transform_view<std::ranges::ref_view<std::vector<int> >, int& (*)(int&)>::_Iterator<true>
.
The argument type of the _Iterator
is named _Const
in the source code for ranges
.
Can you explain me the reason why the ranges
are so designed? Is the problem fixable, or should I build the const_iterator from scratch, and not use the ranges?