Skip to content

Instantly share code, notes, and snippets.

@ozars
Last active May 24, 2023 21:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ozars/9b77cfcae53b90c883b456d1170e77fb to your computer and use it in GitHub Desktop.
Save ozars/9b77cfcae53b90c883b456d1170e77fb to your computer and use it in GitHub Desktop.
Converting user-defined containers to ranges

C++ Ranges require certain concepts to be implemented. If user-defined container doesn't refine those, it won't be treated as Range.

Here is a working minimal example using range-v3, based on this SO answer.

#include <iostream>
#include <iterator>
#include <range/v3/all.hpp>
struct Test {
struct iterator;
struct sentinel;
int counter;
Test() = default;
iterator begin();
sentinel end();
// These are not required.
// sentinel end() const;
// iterator begin() const;
};
struct Test::iterator {
using value_type = int;
using reference = int&;
using pointer = int*;
using iterator_category = std::input_iterator_tag;
using difference_type = ptrdiff_t;
Test* test;
iterator& operator++() {
test->counter++;
return *this;
}
void operator++(int) {
(void)++*this;
}
reference operator*() { return test->counter; }
std::add_const_t<reference> operator*() const { return test->counter; }
bool operator!=(const iterator& rhs) const { return rhs.test != test; }
bool operator!=(const sentinel&) const { return true; }
template <typename T>
bool operator==(T&& t) const { return !(*this != std::forward<T>(t)); }
};
struct Test::sentinel {
bool operator!=(const iterator& iterator) const {
return iterator != *this;
}
// This is not required:
// bool operator!=(const sentinel&) {
// return true;
// }
template <typename T>
bool operator==(T&& t) const { return !(*this != std::forward<T>(t)); }
};
Test::iterator Test::begin() { return {this}; }
Test::sentinel Test::end() { return {}; }
int main() {
auto container = Test();
static_assert(std::is_same_v<decltype(container.begin() == container.end()), bool>);
static_assert(std::is_same_v<decltype(container.end() == container.begin()), bool>);
static_assert(ranges::range<Test&>, "It is not a range");
auto rng = container | ranges::views::take(10);
for (auto n : rng) {
std::cerr << n << std::endl;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment