I don't understand where the requirement for moving comes from. I can't find it in forward_range
and sized_sentinel
...
Basic example:
#include <ranges>
#include <string>
#include <iostream>
class vrange: public std::ranges::view_interface<vrange>
{
public:
vrange(std::string &d): data(d){;};
vrange(const vrange &&) = delete;
auto begin() const noexcept { return data.begin(); };
auto end() const noexcept { return data.end(); };
private:
std::string data;
};
int main(){
std::string h("Hello world");
vrange r(h);
std::cout << r.size() << std::endl;
for (const auto &i: r){
std::cout << i;
}
std::cout << std::endl;
}
removing the call to r.size()
, or defaulting the vrange move constructor and assignment operator makes it compile fine.
compiler message:
/usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g -v12/bits/ranges_util.h: In instantiation of ‘constexpr _Derived& std::ranges::view_interface<_Derived>::_M_derived() [with _Derived = vrange]’:
/usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g -v12/bits/ranges_util.h:101:35: required from ‘constexpr bool std::ranges::view_interface<_Derived>::empty() requires forward_range<_Derived> [with _Derived = vrange]’
w.cpp:25:12: required from here
/usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g -v12/bits/ranges_util.h:70:23: error: static assertion failed
70 | static_assert(view<_Derived>);
| ^~~~~~~~~~~~~~
/usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g -v12/bits/ranges_util.h:70:23: note: constraints not satisfied
In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g -v12/ranges:37:
/usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g -v12/concepts:136:13: required for the satisfaction of ‘constructible_from<_Tp, _Tp>’ [with _Tp = vrange]
/usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g -v12/concepts:150:13: required for the satisfaction of ‘move_constructible<_Tp>’ [with _Tp = vrange]
/usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g -v12/concepts:247:13: required for the satisfaction of ‘movable<_Tp>’ [with _Tp = vrange]
/usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g -v12/concepts:137:30: note: the expression ‘is_constructible_v<_Tp, _Args ...> [with _Tp = vrange; _Args = {vrange}]’ evaluated to ‘false’
137 | = destructible<_Tp> && is_constructible_v<_Tp, _Args...>;
CodePudding user response:
This has nothing to do with size
specifically.
view_interface
is used to build a type that is a view. Well, the ranges::view
concept requires that the type is at least moveable. And view_interface
has a very specific requirement on the type given as its template argument:
Before any member of the resulting specialization of
view_interface
other than special member functions is referenced,D
shall be complete, and model bothderived_from<view_interface<D>>
andview
.
Well, your type does not model view
because it is not moveable. So you broke the rules, and you therefore get undefined behavior. Which can include compile errors happening if you call certain members but not others.