Your question would be clearer if it contained the code you're working with so far. But, reading between the lines, the simplest solution is probably exactly what Peter says in the comments: Simply have your begin
and end
methods expose the begin/end iterators of your private vector
member.
class Book {};
class Library {
std::vector<Book> books_;
public:
auto begin() const { return books_.begin(); }
auto end() const { return books_.end(); }
};
static_assert(std::ranges::contiguous_range<Library>);
static_assert(std::same_as<std::ranges::iterator_t<Library>,
std::vector<Book>::const_iterator>);
~~~
assert(std::ranges::is_sorted(mylibrary, ByAuthor());
Here, my Library
is an iterable (and contiguous) range of Book
objects.
I could make it a mutable range by exposing non-const iteration too:
class Library {
std::vector<Book> books_;
public:
auto begin() { return books_.begin(); }
auto end() { return books_.end(); }
auto begin() const { return books_.begin(); }
auto end() const { return books_.end(); }
};
static_assert(std::same_as<std::ranges::iterator_t<Library>,
std::vector<Book>::iterator>);
static_assert(std::same_as<std::ranges::iterator_t<const Library>,
std::vector<Book>::const_iterator>);
~~~
std::ranges::sort(mylibrary, ByAuthor();
The alternative is to write your own iterator type — a class type that exposes operator*
, operator++
, operator==
, and so on. For a complete working skeleton that you can flesh out with your own contents, see the accepted answer to "In C++20, how do I write a contiguous iterator?" — the answer for random-access iterators will be exactly the same except that you won't provide the element_type
member.