Iterators for circular structures - c++

The following code shows what I currently have. It is an adapter for
circular data-structures. The main function shows how it is used. This
is all nice and fast but I really would like to have iterators over
the structure defined by circ. All approaches up till now involved
either some counting scheme (count the range if with the circulator,
build an iterator that counts increments and decrements) or boolean
values to check if the iterator has been moved to avoid begin and end
being equal.
Are there some common solutions to adapt a circular structure to
iterators? What other work-arounds are possible?
I would like to preserve the iteration speed as much as possible but
am willing to make compromises here. I would value a fully conforming
iterator over a minor speed penalty.
#include <cstddef> // nullptr
#include <iostream>
#include <boost/noncopyable.hpp>
#include <boost/operators.hpp>
// circular structure that we want to iterate over
struct circ : private boost::noncopyable {
unsigned int i;
circ* next;
circ* prev;
};
// whacked up circulator, imagine some template cream here to make it
// generic, omitted to preserve sanity
struct circulator
: public boost::incrementable<circulator>
, public boost::decrementable<circulator>
, public boost::equality_comparable<circulator, circulator>
, public boost::dereferenceable<circulator, circ*>
{
circulator()
: c(nullptr) {}
circulator(circ& c) : c(&c) {}
bool operator==(const circulator& other) const {
return this->c == other.c;
}
circulator& operator++() { c = c->next; return *this; }
circulator& operator--() { c = c->prev; return *this; }
explicit operator bool() const { return c; }
circ& operator*() const { return *c; }
circ* c;
};
int main()
{
circ a, b, c, d;
a.next = &b; a.prev = &a; a.i = 0;
b.next = &c; b.prev = &a; b.i = 1;
c.next = &d; c.prev = &b; c.i = 2;
d.next = &a; d.prev = &c; d.i = 3;
circulator begin{a}, end{a};
if(begin)
do {
std::cout << begin->i << std::endl;
begin = ++begin;
} while(begin != end);
return 0;
}
If need be I can add some of my previous approaches, but they are
rather verbose and would add unnecessary bloat to the question.
EDIT: It would be nice if the resulting iterator would be bidirectional. Although I can give up this requirement.

If it were me, I'd have operator++ notice the terminal condition, and set c to some sentinal value:
circulator(circ& c) : c(&c), start(&c) {}
circulator& operator++() { c = c->next; if(c==start) c=nullptr; return *this; }
Usage:
circulator begin{a}, end;
while(begin != end) {
begin++;
}
Note that this usage defines the end iterator as holding a nullptr, which means that you can't do this:
circulator end;
--end;

Usually, "circulator" means a circular iteration adapter for a linear structure. What you desire is really an inverse adapter: it takes a circular structure, and presents a linear iterator that has a beginning and an end - such concepts simply don't apply to circular iterators or circular structure.
So, to avoid confusion, I'll refer to the iterator as a circ_iterator. The true circulator for your circular structure is trivial, and must not care about any ends or beginnings.
The desired functionality can be had by tagging the iterator:
The idiomatic way of getting start/end iterators for type T is via begin and end in the namespace where T lives, or via member functions of the same name. The instantiation circ_iterator end{a} would be non-idiomatic. Instead, overload begin and end on circ&. Both return an iterator pointing to the argument. begin tags the iterator Default, and end tags the iterator End. See this question for details.
Only the end iterator is special, and all of the typical iterator semantics can be had by adding a small, three-valued tag to the iterator. Its values are:
End: the iterator originated as a result of end;
Inc: the iterator did not originate from end and has been most recently incremented;
Default: otherwise.
An iterator obtained from end will retain its End tag forever. Otherwise, an iterator starts with the Default tag, and switches to Inc on increment, and back to Default on decrement.
Note that begin and end can never be the same, since there's no way for the circular container to have a zero size: a circ item always holds at least one data item. You could, of course represent an absence of a circ instance using a null iterator that compares equal to any other null iterator.
The increment operation is special, since the only legal way to approach the end iterator is by incrementing. When doing so, the following must hold:
You're not incrementing starting at end, since that's illegal.
Only after an increment you might be before the end, or at the end.
Thus, the iterators are identical when their pointers are identical, and:
the other iterator is not tagged End, or
this iterator is not tagged Default (it must be itself End or Inc - recently incremented).
Since the tag is small (2 bits wide), you can assume, or statically assert, that the circ type is aligned to 4 bytes and the platform-specific uintptr_t<->*circ conversions are "sane", and using the tagged pointer trick to retain the tag in the least significant bits of the pointer. I provide both the version that employs the tagged pointer trick, and one that doesn't.
Finally, it's much easier to implement iterators by deriving from boost::iterator_facade. I'm leaving the implementation of const_circ_iterator as an exercise to the reader. It is well documented.
The code compiles on MSVC2012 and also on LLVM 6.
First, let's deal with the tagged pointers - this is a very basic implementation, but will do for our purposes.
// https://github.com/KubaO/stackoverflown/tree/master/questions/circ-
iterator-9993713
#include <boost/iterator/iterator_facade.hpp>
#include <boost/noncopyable.hpp>
#include <boost/operators.hpp>
#include <limits>
#include <iostream>
#include <cassert>
#include <cstdint>
#include <algorithm>
template <typename T, bool merge_tag = false, typename tag_type = uint8_t> class tagged_ptr;
template <typename T, typename tag_type> class tagged_ptr<T, true, tag_type> {
uintptr_t ptr;
typedef std::numeric_limits<uintptr_t> lim;
inline static uintptr_t ptr_of(T* p) {
assert(tag_of(p) == 0);
return uintptr_t(p);
}
inline static uintptr_t tag_mask() { return 3; }
inline uintptr_t ptr_only() const { return ptr & (lim::max() - tag_mask()); }
inline static tag_type tag_of(T* p) { return ((tag_type)(uintptr_t)p) & tag_mask(); }
inline tag_type tag_only() const { return ptr & tag_mask(); }
public:
tagged_ptr(T* p, tag_type t) : ptr(ptr_of(p) | t) { assert(t <= tag_mask()); }
tagged_ptr(const tagged_ptr & other) : ptr(other.ptr) {}
operator T*() const { return reinterpret_cast<T*>(ptr_only()); }
T* operator->() const { return reinterpret_cast<T*>(ptr_only()); }
tagged_ptr & operator=(T* p) { ptr = tag_only() | ptr_of(p); return *this; }
tag_type tag() const { return tag_only(); }
void set_tag(tag_type tag) { assert(tag <= tag_mask()); ptr = tag | ptr_only(); }
};
template <typename T, typename tag_type> class tagged_ptr<T, false, tag_type> {
T* ptr;
tag_type m_tag;
public:
tagged_ptr(T* p, tag_type t) : ptr(p), m_tag(t) {}
tagged_ptr(const tagged_ptr & other) : ptr(other.ptr), m_tag(other.m_tag) {}
operator T*() const { return ptr; }
T* operator->() const { return ptr; }
tagged_ptr & operator=(T* p) { ptr = p; return *this; }
tag_type tag() const { return m_tag; }
void set_tag(tag_type tag) { m_tag = tag; }
};
The circ class can have some convenience constructors to make constructing circular lists easier, and to avoid the mistake you made in your question (a.prev = &a is wrong).
struct circ : private boost::noncopyable {
unsigned int i;
circ* next;
circ* prev;
explicit circ(int i) : i(i), next(nullptr), prev(nullptr) {}
circ(int i, circ& prev) : i(i), next(nullptr), prev(&prev) {
prev.next = this;
}
circ(int i, circ& prev, circ& next) : i(i), next(&next), prev(&prev) {
prev.next = this;
next.prev = this;
}
};
The circ_iterator is then:
class circ_iterator;
circ_iterator end(circ& c);
class circ_iterator
: public boost::iterator_facade<
circ_iterator, circ, boost::bidirectional_traversal_tag
>
{
tagged_ptr<circ> c;
enum { Default, Inc, End };
friend class boost::iterator_core_access;
friend circ_iterator end(circ&);
struct end {};
circ_iterator(circ& c_, end) : c(&c_, End) {}
circ& dereference() const { return *c; }
void increment() {
c = c->next;
if (c.tag() != End) c.set_tag(Inc);
}
void decrement() {
c = c->prev;
if (c.tag() != End) c.set_tag(Default);
}
bool equal(const circ_iterator & other) const {
return this->c == other.c &&
(other.c.tag() != End || this->c.tag() != Default);
}
public:
circ_iterator() : c(nullptr, Default) {}
circ_iterator(circ& c_) : c(&c_, Default) {}
circ_iterator(const circ_iterator& other) : c(other.c) {}
};
circ_iterator begin(circ& c) { return circ_iterator(c); }
circ_iterator end(circ& c) { return circ_iterator(c, circ_iterator::end()); }
Finally, a simple demonstration:
int main()
{
circ a(0), b(1, a), c(2, b), d(3, c, a);
assert(end(a) == end(a));
assert(++--end(a) == end(a));
for (auto it = begin(a); it != end(a); ++it) {
std::cout << it->i << std::endl;
}
std::cout << "*" << std::endl;
for (auto it = ++begin(a); it != --end(a); ++it) {
std::cout << it->i << std::endl;
}
std::cout << "*" << std::endl;
for (auto & c : a)
std::cout << c.i << std::endl;
}
Output:
0
1
2
3
*
1
2
*
0
1
2
3

Related

Create contiguous_iterator for custom class

Summary
I have a custom array class:
template<typename T, int SIZE>
class Array {
private:
T mArray[SIZE];
};
To enable support for std algorithms, with ranges, I want to create an iterator for this class. It would seem that std::contiguous_iterator would be the optimal choice since I can guarantee contiguous memory layout for the data. Following the iterator tutorial I should create a class inside this class. However, I should somehow be (quoted) "For example, instead of the std::forward_iterator_tag tag you would mark your iterator with the std::forward_iterator concept.".
I have a hard time figuring out what the syntax would look like for this, and I have been unable to find a post on the web showcasing this.
Question
How do I complete the following code snippet to implement std::contiguous_iterator for my Array<T,S> class?:
import <iterator>;
template<typename T, int SIZE>
class Array {
public:
const T& operator[](int i) { return mArray[i]; }
T& operator[](int i) { return mArray[i]; }
private:
T mArray[SIZE];
public:
struct Iterator {
Iterator(T* ptr) : mPtr(ptr) {}
private:
T* mPtr;
};
Iterator begin() { return Iterator(&mArray[0]); }
Iterator end() { return Iterator(&mArray[SIZE]); }
};
NOTE: There is a lot of operator overloads. An answer is not required to provide all of them. I just need an example syntax for where to place the concept, then I can probably figure out the rest.
As far as I could tell you need typedefs on the iterator class, so simply using a pointer was not sufficient. Here is an example:
#include <iterator>
#include <algorithm>
template<typename T, int SIZE>
class Array {
public:
const T& operator[](int i) const { return mArray[i]; }
T& operator[](int i) { return mArray[i]; }
private:
T mArray[SIZE];
public:
struct iterator
{
using difference_type=std::ptrdiff_t;
using value_type=std::remove_cv_t<T>;
using pointer=T*;
using reference=T&;
using iterator_category=std::random_access_iterator_tag;
using iterator_concept=std::contiguous_iterator_tag;
using self_type=iterator;
iterator(T *x) : ptr(x) {}
T operator*() { return *ptr; }
T operator->() { return ptr; }
difference_type operator-(const iterator& rhs) { return ptr-rhs.ptr; }
iterator& operator ++() { ++ptr; return *this;}
bool operator !=(const iterator& rhs) { return ptr != rhs.ptr; }
private:
T * ptr;
};
iterator begin() { return &mArray[0]; }
iterator end() { return &mArray[SIZE]; }
};
int foo(Array<int, 7>& a)
{
int sum;
for (auto x : a)
{
sum+=x;
}
return sum;
}
int goo(Array<int, 7>& a, int x)
{
auto ret=std::find(a.begin(), a.end(), x);
if (ret!=a.end()) return *ret;
return 0;
}
Note that you would likely need const_iterator and reverse_iterators for const and non-const ...
Credits
Thanks to #glenn-teitelbaum for pointing me in the right direction. I think I managed to figure out how to do this. It took a long time, so this will hopefully save someone else that trouble.
[Answering my own question]
The iterator should comply with the std::contiguous_iterator concept, so I looked at cppreference for the necessary parts. The concept is defined like this:
template<class I>
concept contiguous_iterator =
std::random_access_iterator<I> &&
std::derived_from</*ITER_CONCEPT*/<I>, std::contiguous_iterator_tag> &&
std::is_lvalue_reference_v<std::iter_reference_t<I>> &&
std::same_as<
std::iter_value_t<I>, std::remove_cvref_t<std::iter_reference_t<I>>
> &&
requires(const I& i) {
{ std::to_address(i) } ->
std::same_as<std::add_pointer_t<std::iter_reference_t<I>>>;
};
So in order to implement this concept, I must first also implement std::random_access_iterator, std::is_derived_from<[...]>, std::is_lvalue_reference_v<[...]>, and so on. This is a recursive process, especially since std::random_access_iterator builds on top of 4 other iterator types. Since this is a C++20 question, I aim to use C++20 features as much as possible (since it greatly simplifies the implementation). This is the complete iterator implementation:
template<typename T, int SIZE>
class Array
{
public:
class Iterator
{
public:
using iterator_category = std::contiguous_iterator_tag;
using iterator_concept = std::contiguous_iterator_tag;
//using difference_type = std::ptrdiff_t; // Likely the same
using difference_type = typename std::iterator<
std::contiguous_iterator_tag, T>::difference_type;
//using value_type = T;
using value_type = std::remove_cv_t<T>; // Using `T` seems sufficient
using pointer = T*;
using reference = T&;
// constructor for Array<T,S>::begin() and Array<T,S>::end()
Iterator(pointer ptr) : mPtr(ptr) {}
// std::weakly_incrementable<I>
Iterator& operator++() { ++mPtr; return *this; }
Iterator operator++(int) { Iterator tmp = *this; ++(*this); return tmp; }
Iterator() : mPtr(nullptr/*&mArray[0]*/) {} // TODO: Unsure which is correct!
// std::input_or_output_iterator<I>
reference operator*() { return *mPtr; }
// std::indirectly_readable<I>
friend reference operator*(const Iterator& it) { return *(it.mPtr); }
// std::input_iterator<I>
// No actions were needed here!
// std::forward_iterator<I>
// In C++20, 'operator==' implies 'operator!='
bool operator==(const Iterator& it) const { return mPtr == it.mPtr; }
// std::bidirectional_iterator<I>
Iterator& operator--() { --mPtr; return *this; }
Iterator operator--(int) { Iterator tmp = *this; --(*this); return tmp; }
// std::random_access_iterator<I>
// std::totally_ordered<I>
std::weak_ordering operator<=>(const Iterator& it) const {
return std::compare_three_way{}(mPtr, it.mPtr);
// alternatively: `return mPtr <=> it.mPtr;`
}
// std::sized_sentinel_for<I, I>
difference_type operator-(const Iterator& it) const { return mPtr - it.mPtr; }
// std::iter_difference<I> operators
Iterator& operator+=(difference_type diff) { mPtr += diff; return *this; }
Iterator& operator-=(difference_type diff) { mPtr -= diff; return *this; }
Iterator operator+(difference_type diff) const { return Iterator(mPtr + diff); }
Iterator operator-(difference_type diff) const { return Iterator(mPtr - diff); }
friend Iterator operator+(difference_type diff, const Iterator& it) {
return it + diff;
}
friend Iterator operator-(difference_type diff, const Iterator& it) {
return it - diff;
}
reference operator[](difference_type diff) const { return mPtr[diff]; }
// std::contiguous_iterator<I>
pointer operator->() const { return mPtr; }
using element_type = T;
private:
T* mPtr;
};
// === STATIC ASSERTS ===
// - to verify correct Iterator implementation!
static_assert(std::weakly_incrementable<Iterator>);
static_assert(std::input_or_output_iterator<Iterator>);
static_assert(std::indirectly_readable<Iterator>);
static_assert(std::input_iterator<Iterator>);
static_assert(std::incrementable<Iterator>);
static_assert(std::forward_iterator<Iterator>);
static_assert(std::bidirectional_iterator<Iterator>);
static_assert(std::totally_ordered<Iterator>);
static_assert(std::sized_sentinel_for<Iterator, Iterator>);
static_assert(std::random_access_iterator<Iterator>);
static_assert(std::is_lvalue_reference_v<std::iter_reference_t<Iterator>>);
static_assert(std::same_as<std::iter_value_t<Iterator>,
std::remove_cvref_t<std::iter_reference_t<Iterator>>>);
static_assert(std::contiguous_iterator<Iterator>);
const T& operator[](int i) const {
if (i < 0 || i >= SIZE) {
throw std::runtime_error("Array index out of bounds");
}
return mArray[i];
}
T& operator[](int i) {
if (i < 0 || i >= SIZE) {
throw std::runtime_error("Array index out of bounds");
}
return mArray[i];
}
Iterator begin() { return Iterator(&mArray[0]); }
Iterator end() { return Iterator(&mArray[SIZE]); }
private:
T mArray[SIZE];
};
// Check that the Array class can be used as a contiguous_range.
static_assert(std::ranges::contiguous_range<Array<int, 10>>);
NOTE: using element_type = T; was necessary because of a bug in the specification, which might be fixed. I found information about that here. Adding this fixed issue with std::to_address<Iterator> not being able to compile, and was the last missing piece in going from std::random_access_iterator to std::contiguous_iterator.
Testing
I did not perform a complete testing suite with all algorithms, but I chose a few which depend on ranges and std::random_access_iterator. It all runs smoothly. I also depend on building standard library headers as module units, because I want to showcase how C++20 features work together.
import <stdexcept>;
import <iostream>;
import <iterator>;
import <algorithm>;
import <random>;
#include <memory> // fails to build header unit!
template<typename T, int SIZE>
class Array
{
[...]
};
int main()
{
Array<int, 10> arr;
for (int i = 0; i < 10; i++) arr[i] = i;
// I need to call std::ragnes::shuffle since that depends on
// std::random_access_iterator, so that is a minimum.
// https://en.cppreference.com/w/cpp/algorithm/ranges/shuffle
std::random_device rd;
std::mt19937 gen{rd()};
std::cout << "before random shuffle:\n";
for (auto& i : arr) std::cout << i << ' ';
std::ranges::shuffle(arr, gen);
std::cout << "\nafter random shuffle:\n";
for (auto& i : arr) std::cout << i << ' ';
std::cout << '\n';
// Also std::ranges::stable_sort is a good check (also random_access_iterator):
// https://en.cppreference.com/w/cpp/algorithm/ranges/stable_sort
std::cout << "after stable_sort:\n";
std::ranges::stable_sort(arr);
for (auto& i : arr) std::cout << i << ' ';
std::cout << '\n';
auto [min,max] = std::ranges::minmax(arr);
std::cout << "min: " << min << ", max: " << max << '\n';
return 0;
}

C++ iterate over members of struct

Say I have a struct:
struct Boundary {
int top;
int left;
int bottom;
int right;
}
and a vector
std::vector<Boundary> boundaries;
What would be the most C++ style way to access the structs to get the sum of top, left, bottom and right separately?
I could write a loop like
for (auto boundary: boundaries) {
sum_top+=boundary.top;
sum_bottom+=boundary.bottom;
...
}
This seems like a lot of repetition. Of course I could do this instead:
std::vector<std::vector<int>> boundaries;
for (auto boundary: boundaries) {
for(size_t i=0; i<boundary.size();i++) {
sums.at(i)+=boundary.at(i)
}
}
But then I'd loose all the meaningful struct member names. Is there a way so that I can write a something like the following function:
sum_top=make_sum(boundaries,"top");
Reflection does not seem to be an option in C++. I am open to use C++ up to Version 14.
std::accumulate(boundaries.begin(), boundaries.end(), 0,
[](Boundary const & a, Boundary const & b) { return a.top + b.top); });
(IIRC the Boundary const &'s can be auto'd in C++17)
This doesn't make it generic for the particular element, which - indeed, due to the lack of reflection - isn't easy to generalize.
There are a few ways to ease your pain, though;
You could use a pointer-to-member, which is fine for your szenario but not very c-plusplus-y:
int Sum(vector<Boundary>const & v, int Boundary::*pMember)
{
return std::accumulate( /*...*/,
[&](Boundary const & a, Boundary const & b)
{
return a.*pMember + b.*pMember;
});
}
int topSum = Sum(boundaries, &Boundary::top);
(For pointer-to-member, see e.g. here: Pointer to class data member "::*")
You could also make this generic (any container, any member type), and you could also replace the pointer-to-member with a lambda (also allowing member functions)
You can achieve the desired effect with Boost Hana reflection:
#include <iostream>
#include <vector>
#include <boost/hana.hpp>
struct Boundary {
BOOST_HANA_DEFINE_STRUCT(Boundary,
(int, top),
(int, left),
(int, bottom),
(int, right)
);
};
template<class C, class Name>
int make_sum(C const& c, Name name) {
int sum = 0;
for(auto const& elem : c) {
auto& member = boost::hana::at_key(elem, name);
sum += member;
}
return sum;
}
int main() {
std::vector<Boundary> v{{0,0,1,1}, {1,1,2,2}};
std::cout << make_sum(v, BOOST_HANA_STRING("top")) << '\n';
std::cout << make_sum(v, BOOST_HANA_STRING("bottom")) << '\n';
}
See Introspecting user-defined types for more details.
I am probably a bit late to the party, but I wanted to add answer inspired by the one of #TobiasRibizel. Instead of adding much boilerplate code to your struct we add more boilerplate code once in the form of an iterator over (specified) members of a struct.
#include <iostream>
#include <string>
#include <map>
template<class C, typename T, T C::* ...members>
class struct_it {
public:
using difference_type = std::ptrdiff_t;
using value_type = T;
using pointer = T*;
using reference = T&;
using iterator_category = std::bidirectional_iterator_tag;
constexpr struct_it (C &c) : _index{0}, _c(c)
{}
constexpr struct_it (size_t index, C &c) : _index{index}, _c(c)
{}
constexpr static struct_it make_end(C &c) {
return struct_it(sizeof...(members), c);
}
constexpr bool operator==(const struct_it& other) const {
return other._index == _index; // Does not check for other._c == _c, since that is not always possible. Maybe do &other._c == &_c?
}
constexpr bool operator!=(const struct_it& other) const {
return !(other == *this);
}
constexpr T& operator*() const {
return _c.*_members[_index];
}
constexpr T* operator->() const {
return &(_c.*_members[_index]);
}
constexpr struct_it& operator--() {
--_index;
return *this;
}
constexpr struct_it& operator--(int) {
auto copy = *this;
--_index;
return copy;
}
constexpr struct_it& operator++() {
++_index;
return *this;
}
constexpr struct_it& operator++(int) {
auto copy = *this;
++_index;
return copy;
}
private:
size_t _index;
C &_c;
std::array<T C::*, sizeof...(members)> _members = {members...}; // Make constexpr static on C++17
};
template<class C, typename T, T C::* ...members>
using cstruct_it = struct_it<const C, T, members...>;
struct boundary {
int top;
int bottom;
int left;
int right;
using iter = struct_it<boundary, int, &boundary::top, &boundary::bottom, &boundary::left, &boundary::right>;
using citer = cstruct_it<boundary, int, &boundary::top, &boundary::bottom, &boundary::left, &boundary::right>;
iter begin() {
return iter{*this};
}
iter end() {
return iter::make_end(*this);
}
citer cbegin() const {
return citer{*this};
}
citer cend() const {
return citer::make_end(*this);
}
};
int main() {
boundary b{1,2,3,4};
for(auto i: b) {
std::cout << i << ' '; // Prints 1 2 3 4
}
std::cout << '\n';
}
It works on C++14, on C++11 the constexpr functions are all const by default so they don't work, but just getting rid of the constexpr should do the trick. The nice thing is that you can choose just some members of your struct and iterate over them. If you have the same few members that you will always iterate over, you can just add a using. That is why I chose to make the pointer-to-members part of the template, even if it is actually not necessary, since I think that only the iterators over the same members should be of the same type.
One could also leave that be, replace the std::array by an std::vector and choose at runtime over which members to iterate.
Without going too much into the memory layout of C++ objects, I would propose replacing the members by 'reference-getters', which adds some boilerplate code to the struct, but except for replacing top by top() doesn't require any changes in the way you use the struct members.
struct Boundary {
std::array<int, 4> coordinates;
int& top() { return coordinates[0]; }
const int& top() const { return coordinates[0]; }
// ...
}
Boundary sum{};
for (auto b : boundaries) {
for (auto i = 0; i < 4; ++i) {
sum.coordinates[i] += b.coordinates[i];
}
}

How to allow range-for loop on my class? [duplicate]

This question already has answers here:
How to make my custom type to work with "range-based for loops"?
(10 answers)
Closed 7 years ago.
I have a class like this:
class Foo {
private:
int a,b,c,d;
char bar;
double m,n
public:
//constructors here
};
I wanna allow range-for loop on my class, e.g.
Foo foo {/*...*/};
for(auto& f : foo) {
//f will be a specific order such as c,b,d,(int)m,(int)bar,a,(int)n
}
How can I achieve this? I was looking at iterator but don't know what are the requirements for a range-for loop. (Please don't ask me to use array or STL type)
The loop is defined to be equivalent to:
for ( auto __begin = <begin-expr>,
__end = <end-expr>;
__begin != __end;
++__begin ) {
auto& f = *__begin;
// loop body
}
where <begin-expr> is foo.begin(), or begin(foo) if there isn't a suitable member function, and likewise for <end-expr>. (This is a simplification of the specification in C++11 6.5.4, for this particular case where the range is a lvalue of class type).
So you need to define an iterator type that supports pre-increment ++it, dereference *it and comparison i1 != i2; and either
give foo public member functions begin() and end(); or
define non-member functions begin(foo) and end(foo), in the same namespace as foo so that they can be found by argument-dependent lookup.
This seems fairly un-C++-like, and rather prone to breakage. What if the iteration order is changed (accidentally or not) during some update in the future? Clients relying on a specific order will break.
All that said if you wish to support this all you have to do is implement your own iterator and provide begin/end methods (or free functions with those names) to provide access. Then the iterator takes care of remembering which attribute it's currently looking at and provides it when dereferenced.
Here is a basic framework I came up with:
#include <iterator>
struct Foo;
template<typename Type>
struct MemberPtrBase {
virtual ~MemberPtrBase() { }
virtual Type get() const = 0;
virtual MemberPtrBase & set(Type const &) = 0;
};
template<typename Class, typename RealType, typename CommonType>
struct MemberPtr : MemberPtrBase<CommonType> {
public:
MemberPtr(Class * object, RealType(Class::*member))
: m_object(object), m_ptr(member)
{ }
CommonType get() const {
return m_object->*m_ptr;
}
MemberPtr & set(CommonType const & val) {
m_object->*m_ptr = val;
return *this;
}
MemberPtr & operator=(RealType const & val) {
return set(val);
}
operator CommonType() const {
return get();
}
private:
Class * m_object;
RealType (Class::*m_ptr);
};
template<typename Class, typename... Types>
struct MemberIterator {
public:
using CommonType = typename std::common_type<Types...>::type;
public:
MemberIterator(Class & obj, std::size_t idx, Types(Class::*...member))
: m_object(obj), m_index(idx), m_members { new MemberPtr<Class, Types, CommonType>(&obj, member)... }
{ }
MemberPtrBase<CommonType> & operator*() const {
return *m_members[m_index];
}
bool operator==(MemberIterator const & it) const {
return (&m_object == &it.m_object) && (m_index == it.m_index);
}
bool operator!=(MemberIterator const & it) const {
return (&m_object != &it.m_object) || (m_index != it.m_index);
}
MemberIterator & operator++() {
++m_index;
return *this;
}
private:
Class & m_object;
std::size_t m_index;
MemberPtrBase<CommonType> * m_members[sizeof...(Types)];
};
struct Foo {
public:
using iterator = MemberIterator<Foo, int, int, int, int>;
public:
Foo(int a, int b, int c, int d)
: m_a(a), m_b(b), m_c(c), m_d(d)
{ }
iterator begin() {
return iterator(*this, 0, &Foo::m_b, &Foo::m_d, &Foo::m_c, &Foo::m_a);
}
iterator end() {
return iterator(*this, 4, &Foo::m_b, &Foo::m_d, &Foo::m_c, &Foo::m_a);
}
private:
int m_a, m_b, m_c, m_d;
};
If you have a basic understanding of variadic templates, I think the code is self-explanatory.
Usage is simple:
#include <iostream>
int main(int argc, char ** argv) {
Foo foo { 1, 2, 3, 4 };
for(auto & mem : foo) {
std::cout << mem.get() << std::endl;
mem.set(3);
}
for(auto & mem : foo) {
std::cout << mem.get() << std::endl;
}
}
A POC can be found on ideone

How do I loop over consecutive pairs in an STL container using range-based loop syntax?

How do I create a custom class to loop over consecutive pairs of items in a STL container using a range-based loop?
This is the syntax and output I want:
std::list<int> number_list;
number_list.push_back(1);
number_list.push_back(2);
number_list.push_back(3);
auto paired_list = Paired(number_list);
for (const auto & pair : paired_list) {
std::printf("The pair is (%d, %d)\n", *(pair[0]), *(pair[1]));
// or
//std::printf("The pair is (%d, %d)\n", *(pair.first), *(pair.second));
}
// output:
// The pair is (1, 2)
// The pair is (2, 3)
I know these (and more) are needed, but I can't figure it out:
template <class T>
class Paired {
???
class iterator {
???
}
iterator begin() {
...
}
iterator end() {
...
}
}
Don't worry about const modifiers.
No boost.
Do not modify or copy objects in the container.
Here's what I would do.
#include <iterator>
#include <utility>
template <typename FwdIt> class adjacent_iterator {
public:
adjacent_iterator(FwdIt first, FwdIt last)
: m_first(first), m_next(first == last ? first : std::next(first)) { }
bool operator!=(const adjacent_iterator& other) const {
return m_next != other.m_next; // NOT m_first!
}
adjacent_iterator& operator++() {
++m_first;
++m_next;
return *this;
}
typedef typename std::iterator_traits<FwdIt>::reference Ref;
typedef std::pair<Ref, Ref> Pair;
Pair operator*() const {
return Pair(*m_first, *m_next); // NOT std::make_pair()!
}
private:
FwdIt m_first;
FwdIt m_next;
};
template <typename FwdIt> class adjacent_range {
public:
adjacent_range(FwdIt first, FwdIt last)
: m_first(first), m_last(last) { }
adjacent_iterator<FwdIt> begin() const {
return adjacent_iterator<FwdIt>(m_first, m_last);
}
adjacent_iterator<FwdIt> end() const {
return adjacent_iterator<FwdIt>(m_last, m_last);
}
private:
FwdIt m_first;
FwdIt m_last;
};
template <typename C> auto make_adjacent_range(C& c) -> adjacent_range<decltype(c.begin())> {
return adjacent_range<decltype(c.begin())>(c.begin(), c.end());
}
#include <iostream>
#include <vector>
using namespace std;
void test(const vector<int>& v) {
cout << "[ ";
for (const auto& p : make_adjacent_range(v)) {
cout << p.first << "/" << p.second << " ";
}
cout << "]" << endl;
}
int main() {
test({});
test({11});
test({22, 33});
test({44, 55, 66});
test({10, 20, 30, 40});
}
This prints:
[ ]
[ ]
[ 22/33 ]
[ 44/55 55/66 ]
[ 10/20 20/30 30/40 ]
Notes:
I haven't exhaustively tested this, but it respects forward iterators (because it doesn't try to use operations beyond ++, !=, and *).
range-for has extremely weak requirements; it doesn't require all of the things that forward iterators are supposed to provide. Therefore I have achieved range-for's requirements but no more.
The "NOT m_first" comment is related to how the end of the range is approached. An adjacent_iterator constructed from an empty range has m_first == m_next which is also == last. An adjacent_iterator constructed from a 1-element range has m_first pointing to the element and m_next == last. An adjacent_iterator constructed from a multi-element range has m_first and m_next pointing to consecutive valid elements. As it is incremented, eventually m_first will point to the final element and m_next will be last. What adjacent_range's end() returns is constructed from (m_last, m_last). For a totally empty range, this is physically identical to begin(). For 1+ element ranges, this is not physically identical to a begin() that has been incremented until we don't have a complete pair - such iterators have m_first pointing to the final element. But if we compare iterators based on their m_next, then we get correct semantics.
The "NOT std::make_pair()" comment is because make_pair() decays, while we actually want a pair of references. (I could have used decltype, but iterator_traits will tell us the answer too.)
The major remaining subtleties would revolve around banning rvalues as inputs to make_adjacent_range (such temporaries would not have their lives prolonged; the Committee is studying this issue), and playing an ADL dance to respect non-member begin/end, as well as built-in arrays. These exercises are left to the reader.
edit I was using transform.
Use adjacent_difference.
The second version takes a binary function which transforms the two values into a new
(different) value:
string make_message(int first, int second) {
ostringstream oss;
oss << "The pair is (" << first << ", " << second << ")";
return oss.str();
}
We can now transform the adjacent pairs into a third range. We'll use the ostream_iterator to use cout like a range:
list<int> numbers;
//...
adjacent_difference(numbers.begin(), numbers.end(),
ostream_iterator<string>(cout, "\n"),
make_message);
2nd edit
I found a question on comp.lang.c++.moderated asking why there aren't more 'adjacent' functions in the standard library such as for_each_adjacent. The reply said they were trivial to implement using std::mismatch.
I think this would be a better direction to go than implementing a special adjacent iterator.
Try this.
#include <list>
#include <iostream>
template<class T, class TIter = typename T::iterator, class TVal = typename T::value_type>
class PairedImpl {
T& m_t;
public:
class Iter {
TIter m_it;
public:
Iter(const TIter & it) : m_it(it) {}
bool operator!=(const Iter& it) { return m_it != it.m_it; }
Iter& operator++() { ++m_it; return *this; }
const Iter & operator *() const { return *this; }
const TVal & first() const { return *m_it; }
const TVal & second() const { return *std::next(m_it); }
};
PairedImpl(T& t) : m_t(t) {}
Iter begin() { return Iter(m_t.begin()); }
Iter end() {
TIter end = m_t.end();
return Iter(m_t.empty() ? end : --end);
}
};
template<class T>
PairedImpl<T> Paired(T& t) {
return PairedImpl<T>(t);
}
Usage
int main()
{
std::list<int> lst;
lst.push_back(1);
lst.push_back(2);
lst.push_back(3);
lst.push_back(4);
lst.push_back(5);
for (const auto & pair : Paired(lst)) {
std::cout << "(" << pair.first() << ", " << pair.second() << ")" << std::endl;
}
return 0;
}
Okay, an hour with no answers, I've come up with a solution which works. Note that this uses my own FixedLengthVector which is exactly what it sounds like.
template <class T>
class Grouped {
private:
// length of grouped objects
static const unsigned length_ = 2;
// hold pointer to base container to avoid comparing incompatible iterators
T * base_container_;
public:
// constructor
Grouped(T & base_container) :
base_container_(&base_container) {
}
// iterator
class iterator {
private:
// hold pointer to base container to avoid comparing incompatible iterators
T * base_container_;
// hold pointers to objects in base container
FixedLengthVector<length_, typename T::value_type *> ptr_;
// hold iterator to last object
typename T::iterator last_iterator_;
public:
// constructor
iterator(T & base_container, typename T::iterator & it)
: base_container_(&base_container),
last_iterator_(it) {
// set up pointers if possible
unsigned i = 0;
// check for end iterator
if (last_iterator_ == base_container_->end()) {
ptr_.fill(NULL);
return;
}
// set up first object
ptr_[0] = &*last_iterator_;
// set up next objects
for (unsigned i = 1; i < length_; ++i) {
++last_iterator_;
if (last_iterator_ == base_container_->end()) {
ptr_.fill(NULL);
return;
}
ptr_[i] = &*last_iterator_;
}
}
// dereference operator
FixedLengthVector<length_, typename T::value_type *> & operator * (void) {
assert(ptr_[0] != NULL);
return ptr_;
}
// pre-increment
iterator & operator ++ (void) {
// can't increase past end
assert(last_iterator_ != base_container_->end());
// find next iterator
++last_iterator_;
if (last_iterator_ == base_container_->end()) {
ptr_.fill(NULL);
return * this;
}
// cycle pointers left
for (unsigned i = 1; i < length_; ++i) {
ptr_[i - 1] = ptr_[i];
}
ptr_[length_ - 1] = &*last_iterator_;
return * this;
}
// equality comparison
bool operator == (const iterator & that) const {
return base_container_ == that.base_container_ &&
last_iterator_ == that.last_iterator_;
}
// inequality comparison
bool operator != (const iterator & that) const {
return !(*this == that);
}
};
// end iterator
iterator end() {
return iterator(*base_container_, base_container_->end());
}
// begin iterator
iterator begin() {
return iterator(*base_container_, base_container_->begin());
}
};

Is there a range class in C++11 for use with range based for loops?

I found myself writing this just a bit ago:
template <long int T_begin, long int T_end>
class range_class {
public:
class iterator {
friend class range_class;
public:
long int operator *() const { return i_; }
const iterator &operator ++() { ++i_; return *this; }
iterator operator ++(int) { iterator copy(*this); ++i_; return copy; }
bool operator ==(const iterator &other) const { return i_ == other.i_; }
bool operator !=(const iterator &other) const { return i_ != other.i_; }
protected:
iterator(long int start) : i_ (start) { }
private:
unsigned long i_;
};
iterator begin() const { return iterator(T_begin); }
iterator end() const { return iterator(T_end); }
};
template <long int T_begin, long int T_end>
const range_class<T_begin, T_end>
range()
{
return range_class<T_begin, T_end>();
}
And this allows me to write things like this:
for (auto i: range<0, 10>()) {
// stuff with i
}
Now, I know what I wrote is maybe not the best code. And maybe there's a way to make it more flexible and useful. But it seems to me like something like this should've been made part of the standard.
So is it? Was some sort of new library added for iterators over a range of integers, or maybe a generic range of computed scalar values?
The C++ standard library does not have one, but Boost.Range has boost::counting_range, which certainly qualifies. You could also use boost::irange, which is a bit more focused in scope.
C++20's range library will allow you to do this via view::iota(start, end).
As far as I know, there is no such class in C++11.
Anyway, I tried to improve your implementation. I made it non-template, as I don't see any advantage in making it template. On the contrary, it has one major disadvantage : that you cannot create the range at runtime, as you need to know the template arguments at compile time itself.
//your version
auto x = range<m,n>(); //m and n must be known at compile time
//my version
auto x = range(m,n); //m and n may be known at runtime as well!
Here is the code:
class range {
public:
class iterator {
friend class range;
public:
long int operator *() const { return i_; }
const iterator &operator ++() { ++i_; return *this; }
iterator operator ++(int) { iterator copy(*this); ++i_; return copy; }
bool operator ==(const iterator &other) const { return i_ == other.i_; }
bool operator !=(const iterator &other) const { return i_ != other.i_; }
protected:
iterator(long int start) : i_ (start) { }
private:
unsigned long i_;
};
iterator begin() const { return begin_; }
iterator end() const { return end_; }
range(long int begin, long int end) : begin_(begin), end_(end) {}
private:
iterator begin_;
iterator end_;
};
Test code:
int main() {
int m, n;
std::istringstream in("10 20");
if ( in >> m >> n ) //using in, because std::cin cannot be used at coliru.
{
if ( m > n ) std::swap(m,n);
for (auto i : range(m,n))
{
std::cout << i << " ";
}
}
else
std::cout <<"invalid input";
}
Output:
10 11 12 13 14 15 16 17 18 19
Onine demo.
I wrote a library called range for exactly the same purpose except it is a run-time range, and the idea in my case came from Python. I considered a compile-time version, but in my humble opinion there is no real advantage to gain out the compile-time version. You can find the library on bitbucket, and it is under Boost License: Range. It is a one-header library, compatible with C++03 and works like charm with range-based for loops in C++11 :)
Features:
A true random access container with all the bells and whistles!
Ranges can be compared lexicographically.
Two functions exist(returns
bool), and find(returns iterator) to check the existence of a number.
The library is unit-tested using CATCH.
Examples of basic
usage, working with standard containers, working with standard
algorithms and working with range based for loops.
Here is a one-minute introduction. Finally, I welcome any suggestion about this tiny library.
I found that boost::irange was much slower than the canonical integer loop. So I settled on the following much simpler solution using a preprocessor macro:
#define RANGE(a, b) unsigned a=0; a<b; a++
Then you can loop like this:
for(RANGE(i, n)) {
// code here
}
This range automatically starts from zero. It could be easily extended to start from a given number.
Here is a simpler form which is working nicely for me. Are there any risks in my approach?
r_iterator is a type which behaves, as much as possible, like a long int. Therefore many operators such as == and ++, simply pass through to the long int. I 'expose' the underlying long int via the operator long int and operator long int & conversions.
#include <iostream>
using namespace std;
struct r_iterator {
long int value;
r_iterator(long int _v) : value(_v) {}
operator long int () const { return value; }
operator long int& () { return value; }
long int operator* () const { return value; }
};
template <long int _begin, long int _end>
struct range {
static r_iterator begin() {return _begin;}
static r_iterator end () {return _end;}
};
int main() {
for(auto i: range<0,10>()) { cout << i << endl; }
return 0;
}
(Edit: - we can make the methods of range static instead of const.)
This might be a little late but I just saw this question and I've been using this class for a while now :
#include <iostream>
#include <utility>
#include <stdexcept>
template<typename T, bool reverse = false> struct Range final {
struct Iterator final{
T value;
Iterator(const T & v) : value(v) {}
const Iterator & operator++() { reverse ? --value : ++value; return *this; }
bool operator!=(const Iterator & o) { return o.value != value; }
T operator*() const { return value; }
};
T begin_, end_;
Range(const T & b, const T & e) : begin_(b), end_(e) {
if(b > e) throw std::out_of_range("begin > end");
}
Iterator begin() const { return reverse ? end_ -1 : begin_; }
Iterator end() const { return reverse ? begin_ - 1: end_; }
Range() = delete;
Range(const Range &) = delete;
};
using UIntRange = Range<unsigned, false>;
using RUIntRange = Range<unsigned, true>;
Usage :
int main() {
std::cout << "Reverse : ";
for(auto i : RUIntRange(0, 10)) std::cout << i << ' ';
std::cout << std::endl << "Normal : ";
for(auto i : UIntRange(0u, 10u)) std::cout << i << ' ';
std::cout << std::endl;
}
have you tried using
template <class InputIterator, class Function>
Function for_each (InputIterator first, InputIterator last, Function f);
Most of the time fits the bill.
E.g.
template<class T> void printInt(T i) {cout<<i<<endl;}
void test()
{
int arr[] = {1,5,7};
vector v(arr,arr+3);
for_each(v.begin(),v.end(),printInt);
}
Note that printInt can OFC be replaced with a lambda in C++0x.
Also one more small variation of this usage could be (strictly for random_iterator)
for_each(v.begin()+5,v.begin()+10,printInt);
For Fwd only iterator
for_each(advance(v.begin(),5),advance(v.begin(),10),printInt);
You can easily generate an increasing sequence in C++11 using std::iota():
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
template<typename T>
std::vector<T> range(T start, T end)
{
std::vector<T> r(end+1-start, T(0));
std::iota(r.begin(), r.end(), T(start));//increasing sequence
return r;
}
int main(int argc, const char * argv[])
{
for(auto i:range<int>(-3,5))
std::cout<<i<<std::endl;
return 0;
}