How to specialise a type to being a range?

Viewed 53

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?

0 Answers
Related