I'm rolling a custom, standard-like container and I'd like to have it compatible with the boost::range
library.
So far it works with all the STL algorithms and it also satisfies the following:
BOOST_CONCEPT_ASSERT((boost::InputIterator<my_container::const_iterator>));
BOOST_CONCEPT_ASSERT((boost::Container<my_container>));
But when I try to use it in this context:
auto r = c | boost::adaptors::indexed();
It seems to be missing some templated metadata. The errors are something like
error: no type named 'type' in boost::range::iterator<my_container, void>
>> typename range_iterator<SinglePassRange>::type
Is there a similar concept assert I can use to help me complete the missing implementation for my type? Or maybe even an article explaining how to make a container boost::range
compatible? I'm assuming I do not need to actually include boost types in my implementation, since the STL obviously doesn't.
Any help greatly appreciated! :-)
Edit: minimal(ish) example
#include <catch2/catch.hpp>
#include <boost/concept_check.hpp>
#include <boost/concept/assert.hpp>
#include <boost/range/adaptor/indexed.hpp>
#include <algorithm>
SCENARIO("container")
{
class my_container
{
public:
class const_iterator
{
public:
using value_type = const int;
using pointer = const int*;
using reference = const int&;
using difference_type = std::ptrdiff_t;
using iterator_category = std::input_iterator_tag;
const_iterator() = default;
bool operator==(const_iterator other) const noexcept { return d == other.d; }
bool operator!=(const_iterator other) const noexcept { return !(*this == other); }
reference operator*() const { return *d; }
pointer operator->() const { return d; }
const_iterator& operator++() { ++d; return *this; }
const_iterator operator++(int) { return d++; }
private:
friend my_container;
const_iterator(const int* p) : d(p) {}
const int* d{nullptr};
};
using value_type = int;
using const_reference = const int&;
using const_pointer = const int*;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
my_container() : data({0, 1, 2, 3, 4}) {}
const_iterator begin() const { return const_iterator(data.data()); }
const_iterator end() const { return const_iterator(data.data() + 5); }
size_type size() const { return 5; }
size_type max_size() const { return 5; }
bool empty() const { return false; }
private:
std::array<int, 5> data;
};
BOOST_CONCEPT_ASSERT((boost::InputIterator<my_container::const_iterator>));
BOOST_CONCEPT_ASSERT((boost::Container<my_container>));
GIVEN("a container") {
my_container container;
WHEN("use std::algorithms") {
auto itr = std::find(container.begin(), container.end(), 3);
THEN("element is found") {
CHECK(itr != container.end());
}
}
WHEN("use boost range") {
// wont compile
auto r = container | boost::adaptors::indexed();
}
}
}
You need iterator
as well as const_iterator
. Try:
using iterator = const_iterator;