I've been trying to make a custom type fit the requirement of being a range. In the c++ standard a range is defined as following:
template< class T >
concept range = requires(T& t) {
ranges::begin(t); // equality-preserving for forward iterators
ranges::end (t);
};
So as you can see in my example I have overriden the needed functions. However, it doesn't compile for me as it can't find the const versions of the iterators:
prog.cc: In instantiation of 'void some_algorithm(const range&) [with range = Foo]':
prog.cc:42:21: required from here
prog.cc:29:3: error: passing 'const Foo' as 'this' argument discards qualifiers [-fpermissive]
29 | for (const auto& x : r)
| ^~~
prog.cc:11:8: note: in call to 'auto Foo::begin()'
11 | auto begin() { return vec.begin(); }
| ^~~~~
prog.cc:29:3: error: passing 'const Foo' as 'this' argument discards qualifiers [-fpermissive]
29 | for (const auto& x : r)
| ^~~
prog.cc:12:8: note: in call to 'auto Foo::end()'
12 | auto end() { return vec.end(); }
Here is the code I used:
// This file is a "Hello, world!" in C++ language by GCC for wandbox.
#include <iostream>
#include <cstdlib>
#include <ranges>
#include <vector>
struct Foo
{
std::vector<int> vec;
auto begin() { return vec.begin(); }
auto end() { return vec.end(); }
auto cbegin() const { return vec.cbegin(); }
auto cend() const { return vec.cend(); }
auto size() const { return vec.size(); }
};
namespace std::ranges
{
auto begin(Foo& x) { return x.begin(); }
auto end(Foo& x) { return x.end(); }
auto cbegin(const Foo& x) { return x.cbegin(); }
auto cend(const Foo& x) { return x.cend(); }
}
template <std::ranges::range range>
void some_algorithm(const range& r)
{
for (const auto& x : r)
{
std::cout << x << '\n';
}
}
int main()
{
auto f = Foo { { 1, 2, 3, 4 } };
some_algorithm(f.vec); // this works!
//some_algorithm(f); // this doesn't compile!
}
However, when I remove the const from the parameter of some_algorithm it compiles just fine.
Someone has an idea to help me?