Implementing an iterator for a set of handles - c++

I'm working with an awkward C library interface for a database containing a set of objects. The objects have a type and lets say that objects of type A contain a set of B objects and so on. Access to an object is via a handle which are defined as follows:
typedef struct
{
int handle;
} AHandleT;
typedef struct
{
int handle;
} BHandleT;
To iterate over an A object's B children, the following functions are used:
ReturnT getB(AHandleT /*in*/, BHandleT* /*out*/)
ReturnT getBNext(BHandleT /*in*/, BHandleT* /*out*/)
Likewise for iterating over a set of B objects:
ReturnT getC(BHandleT handle/*in*/, CHandleT* subHandle/*out*/)
ReturnT getCNext(CHandleT handle/*in*/, CHandleT* next/*out*/)
In order to work with this interface from C++ I have made the following iterator and I would appreciate your advice with regard to its implementation. Additionally, do you think this is a good approach? Keep in mind that I'm quite new to C++ and I will be writing my code using TDD.
template<class HandleT>
class HandleIterator
{
public:
typedef ReturnT (*GetNext)(HandleT, HandleT*);
HandleIterator(): m_isLast(true)
{
}
template<class ParentHandleT>
HandleIterator(const ParentHandleT parentHandle, ReturnT (*getFirstChild)(ParentHandleT, HandleT*), GetNext getNext): m_isLast(false), m_getNext(getNext)
{
ReturnT rc = getFirstChild(parentHandle, &m_currentHandle);
if(rc == NotExisting)
{
m_isLast = true;
}
}
void operator++()
{
ReturnT rc = m_getNext(m_currentHandle, &m_currentHandle);
if(rc == NotExisting)
{
m_isLast = true;
}
}
void operator++(int)
{
++(*this);
}
const HandleT& operator*() const
{
return m_currentHandle;
}
const HandleT* operator->() const
{
return &m_currentHandle;
}
friend bool operator==(const HandleIterator& left, const HandleIterator& right)
{
return left.m_isLast == right.m_isLast;
}
friend bool operator!=(const HandleIterator& left, const HandleIterator& right)
{
return !(left == right);
}
protected:
HandleT m_currentHandle;
bool m_isLast;
GetNext m_getNext;
};
Once I have a handle, I can then get the data contained within the object using functions of the following form, from the C interface:
ReturnT getAName(AHandleT)
ReturnT getBName(BHandleT)
ReturnT getBOnlyProprty(BHandleT)
But that's the next stage.
etc.

Your implementation is quite good, especially for a beginner.
Just a couple of remarks:
In the constructor, why pass getFirstChild instead of providing the first child directly ?
The canonical signature for ++ are T& operator++() and T operator++(int)
== should compare more than m_isLast, otherwise it's confusing. Cannot you compare the handles too ?
Finally, when implementing an iterator, consider inheriting from std::iterator. It does not have any virtual method but provides the typedef that are usually expected in an iterator and will remind you that you need to pick a category: std::forward_iterator_tag here, most probably.

Related

C++: "Iterable<T>" interface

What I want to achieve is probably easily explained: Consider I have an abstract class that I know will contain multiple objects of known type. However the actual container holding these objects will be implemented in sub-classes.
In my abstract base class I now want to provide an interface to iterate over these objects. Given that I don't know (or rather don't want to fix) the type of container, I thought that iterators would probably be my best bet.
A conceptual declaration of this class might look like this:
class MyClass {
public:
// Other interface methods, e.g. size()
virtual Iterable<MyObject> objects() = 0;
};
The intention here is that I'll be able to iterate over the nested objects of my class like this:
MyClass *class = new ImplementationOfClass();
for (const MyObject &obj : class->objects()) {
// Do stuff with obj
}
The issue I am facing however is that I can't seem to figure out how Iterable<MyObject> should be defined. The key property of this object is that at the time of defining this class I can only specify that the returned value will be iterable (using STL-style iterators) and will yield objects of type MyObject when the used iterator is dereferenced.
Normally I would use an abstract class on its own for this but it seems that this is very tricky (impossible?) since iterators are always passed by value and thus to my knowledge no Polymorphism is possible.
Questions dealing with how to pass arbitrary iterator types as arguments into a function always come up with the "use templates" answer. However I think in my case I can't use templates for that. This assumption might be wrong though, so feel free to correct me.
Essentially the barrier I always run into is that at some point I have to write down the iterator type explicitly which in my case I can't. I thought about using a template for that but this would then inhibit proper Polymorphism (I think?) because the user of that abstract interface seems to have the burden of explicitly initializing the correct template. The whole point of all of this however is that the caller does not have to care about the underlying structure.
TL;DR: Is there a way to create an interface class that only promises to be iterable and that dereferencing an iterator will yield an object of type T?
With the help of #FrançoisAndrieux and a hint from https://stackoverflow.com/a/4247445/3907364, I was able to come up with an approach to my problem.
Essentially the idea is to create an iterator-wrapper that stores a function to obtain an object of the given type if given an index. That index is then what is iterated on.
The nice thing about this is that the iterator interface is fixed by specifying the type of object that dereferencing it should return. The polymorphism comes into play by making the member function objects() virtual so that each sub-class can construct the iterator itself, providing a custom function pointer. Thus as long as there is a way to map an index to the respective element in the container (whichever is used), this trick is usable.
Note that you can either directly use pointers to e.g.std::vector<T>::at or create a custom function that will return the respective element.
Here's the implementation for the iterator (The implementation could probably be improved upon but it seems to get the job done):
template< typename T > struct iterator_impl {
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = T;
using pointer = T *;
using reference = T &;
using access_function_t = std::function< T &(std::size_t) >;
// regular Ctor
iterator_impl(std::size_t start, access_function_t &func, const void *id)
: m_index(start), m_func(func), m_id(id) {}
// function-move Ctor
iterator_impl(std::size_t start, access_function_t &&func, const void *id)
: m_index(start), m_func(func), m_id(id) {}
// copy Ctor
iterator_impl(const iterator_impl &) = default;
// move ctor
iterator_impl(iterator_impl &&other) {
std::swap(m_index, other.m_index);
m_func = std::move(other.m_func);
std::swap(m_id, other.m_id);
}
// copy-assignment
iterator_impl &operator=(const iterator_impl &other) = default;
// prefix-increment
iterator_impl &operator++() {
++m_index;
return *this;
}
// postfix-increment
iterator_impl operator++(int) {
iterator_impl old = *this;
++(*this);
return old;
}
bool operator==(const iterator_impl &other) { return m_index == other.m_index && m_id == other.m_id; }
bool operator!=(const iterator_impl &other) { return !(*this == other); }
T &operator*() { return m_func(m_index); }
T *operator->() { return &m_func(m_index); };
protected:
std::size_t m_index = 0;
access_function_t m_func;
const void *m_id = nullptr;
};
Note that I had to introduce the m_id member variable as a means to properly compare iterators (std::function can't be compared using ==). it is meant to be e.g. the address of the container the elements are contained in. Its sole purpose is to make sure that 2 iterators that happen to have the same index but are iterating over completely different sets are not considered equal.
And based on that here's an implementation of an Iterable<T>:
template< typename T > struct Iterable {
using iterator = iterator_impl< T >;
using const_iterator = iterator_impl< const std::remove_const_t< T > >;
Iterable(std::size_t start, std::size_t end, typename iterator_impl< T >::access_function_t &func, const void *id)
: m_begin(start, func, id), m_end(end, func, id) {}
iterator begin() { return m_begin; }
iterator end() { return m_end; }
const_iterator begin() const { return m_begin; }
const_iterator end() const { return m_end; }
const_iterator cbegin() const { return m_begin; }
const_iterator cend() const { return m_end; }
protected:
iterator m_begin;
iterator m_end;
};

Statically wrapping a library's polymorphic iterator without exposing the library to the user

I am currently integrating a datastore library into my application. I need to be able to mock this datastore (which is I/O intensive) for my unit tests, therefore creating a wrapper around that library's interface.
Unfortunately, in its interface, this library returns iterators as pointers and not as values, because they are polymorphic at runtime.
My issue is that because of the layer of polymorphism I am adding, it seems unavoidable to add iterators that are polymorphic at runtime, therefore incurring a new level of indirection and some more dynamic allocation...
// Library code
class LibIterator
{
// pure virtual methods
};
class LibDataStore
{
LibIterator* getIt();
};
// My interface
class IMyIterator{
// pure virtual methods
};
class MyLibIterator : public IMyIterator
{
std::unique_ptr<LibIterator> m_iterator;
};
class MyIterator
{
std::unique_ptr<MyLibIterator> m_iterator;
};
class IMyDataStore
{
MyIterator getIt();
};
That is an awful lot of pointers to dereference, of virtual dispatch on each use of any method of the iterator, plus at least 2 dynamic allocations (the lib iterator + mine) for each iterator creation...
I was thinking of using CRTP to help with this, but I can't figure out a way to prevent code using IMyDataStore to see the concrete implementation of the iterator bleeding through MyIterator's type.
Is there any trick I might have missed?
template<class T, std::size_t sz, std::size_t algn>
struct poly {
if you are not afraid yet you should be
poly_vtable<T> const* vtable=0;
std::aligned_storage_t<sz, algn> data;
we can cover the vtable later.
T* get() { return vtable->get(&data); }
T const* get() const { return vtable->get((void*)&data); }
example use of vtable. Here is setup:
template<class U, class...Args>
U* emplace(Args&&...args){
static_assert(sizeof(U)<=sz && alignof(U)<=algn, "type too large");
clear();
U* r = ::new((void*)&data) U(std::forward<Args>(args)...);
vtable = get_poly_vtable<T,U>();
return r;
}
copy:
poly(poly const& o){
if (!o.vtable) return;
o.vtable->copy( &data, &o.data );
vtable=o.vtable;
}
poly(poly&& o){
if (!o.vtable) return;
o.vtable->move( &data, &o.data );
vtable=o.vtable;
}
poly& operator=(poly const& rhs) {
if (this == &rhs) return *this;
clear();
if (!rhs.vtable) return *this;
rhs.vtable->copy( &data, &rhs.data );
vtable = rhs.vtable;
return *this;
}
poly& operator=(poly&& rhs) {
if (this == &rhs) return *this;
clear();
if (!rhs.vtable) return *this;
rhs.vtable->move( &data, &rhs.data );
vtable = rhs.vtable;
return *this;
}
destruction:
void clear(){
if (!vtable) return;
vtable->dtor(&data);
vtable=nullptr;
}
~poly(){clear();}
pointer like operations:
explicit operator bool()const{return vtable;}
T& operator*(){ return *get();}
T const& operator*() const{ return *get();}
T* operator->(){ return get();}
T const* operator->() const{ return get();}
construct from a type derived from T:
template<class U,
class dU=std::decay_t<U>,
class=std::enable_if_t<!std::is_same<dU, poly>{}>,
class=std::enable_if_t<std::is_base_of<T, dU>{}>
>
poly(U&& u) {
emplace<std::decay_t<U>>( std::forward<U>(u) );
}
};
note that this type when const refers to a const value.
The idea is that poly<T> is a polymorphic value of type T. It has size limits.
You can use the T* vtable to arrange for polymorphism of other operations.
template<class T>
struct poly_vtable{
T*(*get)(void*)=0;
void(*copy)(void*,void const*)=0;
void(*move)(void*,void*)=0;
void(*dtor)(void*)=0;
};
template<class T, class U>
poly_vtable<T> make_poly_vtable() {
return {
[](void* ptr)->T*{ return static_cast<U*>(ptr); },
[](void* dest, void const* src){ ::new(dest) U(*static_cast<U const*>(src)); },
[](void* dest, void* src){ ::new(dest) U(std::move(*static_cast<U*>(src))); },
[](void* ptr){ static_cast<U*>(ptr)->~U(); }
};
}
template<class T, class U>
poly_vtable<T> const* get_poly_vtable() {
static const auto r = make_poly_vtable<T,U>();
return &r;
}
get_poly_vtable<T,U>() returns a pointer to a static local poly_vtable<T> with each operation implemented.
Live example.
Now you can have a vtable based polymorphic value type.
The same technique can be extended to more operations; simply cast-to-base and using real vtables is easier.
Using this, you store a poly<IMyIterator, 64, alignof(IMyIterator)>. This is a value type containing some buffer of 64 bytes.
Another approach to reduce indirection would be to replace the concept of per-item visitation with possibly repeated range visitation.
If you visit a range of 10 items at once per callback, then the overhead of invoking virtual methods is up to 10 times less than one per callback.
You can create input iterators with a range object that has a buffer for up to 10 items in it and who automatically rebuild it when you reach the end, if there are more available, getting the data in batches.

Defining a proxy-based OutputIterator in terms of boost::iterator_facade

I wrote this C++17 code and expected it to work out of the box.
class putc_iterator : public boost::iterator_facade<
putc_iterator,
void,
std::output_iterator_tag
>
{
friend class boost::iterator_core_access;
struct proxy {
void operator= (char ch) { putc(ch, stdout); }
};
auto dereference() const { return proxy{}; }
void increment() {}
bool equal(const putc_iterator&) const { return false; }
};
I'm trying to match the behavior of all the standard OutputIterators by setting my iterator's member typedefs value_type and reference to void (since those types are meaningless for an iterator whose operator* doesn't return a reference).
However, Boost complains:
In file included from prog.cc:2:
/opt/wandbox/boost-1.63.0/clang-head/include/boost/iterator/iterator_facade.hpp:333:50: error: cannot form a reference to 'void'
static result_type apply(Reference const & x)
^
It looks like Boost is trying to hard-code the generated operator*'s signature as reference operator*() const. That is, boost::iterator_facade could deduce the proper return type of operator*() by simply passing along whatever was returned by dereference(); but for some reason it's just not playing along.
What's the solution? I can't pass proxy as a template parameter of the base class since proxy hasn't been defined yet. I could pull proxy out into a detail namespace:
namespace detail {
struct proxy {
void operator= (char ch) { putc(ch, stdout); }
};
}
class putc_iterator : public boost::iterator_facade<
putc_iterator,
void,
std::output_iterator_tag,
detail::proxy
>
{
friend class boost::iterator_core_access;
auto dereference() const { return detail::proxy{}; }
void increment() {}
bool equal(const putc_iterator&) const { return false; }
};
but that seems awkward and is definitely something that "shouldn't be necessary."
Is this a bug in iterator_facade? Is it a feature-not-a-bug? If the latter, then how am I supposed to use it to create OutputIterators?
Also, a minor nitpick: even my workaround with the detail namespace is "wrong" in the sense that it makes std::is_same_v<putc_iterator::reference, detail::proxy> when what I want (for parity with the standard iterators) is std::is_same_v<putc_iterator::reference, void>.
Boost Iterator Facade was good at the time, but now it is outdated as it is not very flexible (it doesn't play well with auto and with r-value references that in principle can be creating by dereferencing a r-value iterator). I am not againts the facade concept, but it could be upgraded to C++11.
In addition now with C++11 is easier to write iterator from scratch.
Anyway, if you need to define a reference just to comply with the arguments to be passed, (and if you promise not use it) you can use void* instead of void. (Or perhaps for consistency use proxy& and define it outside the class).
class putc_iterator : public boost::iterator_facade<
putc_iterator,
void*,
std::output_iterator_tag
>
{
friend class boost::iterator_core_access;
struct proxy {
void operator= (char ch) { putc(ch, stdout); }
};
auto dereference() const { return proxy{}; }
void increment() {}
bool equal(const putc_iterator&) const { return false; }
};

Any "for each" like hint

I have two classes for example
struct point{
dint data
};
class data{
...
public:
point left;
point right;
..... //more that 50 members of point
point some_other_point;
}example;
Is it possible use something like "for each point in example" in this situation?
Because now I need to modify many functions if I add one more point to data.
Or maybe, there is any other idea about it.
No, you cannot enumerate members of a type, because C++ does not have the concept of reflection.
This is a common use case for an array, a vector or a map.
Yes, and there are two ways to do so:
an iterator class, for external iteration
a visitation method, for internal iteration
Then the iteration logic is encapsulated in either of those classes and all the code just uses them.
Using the iterator class.
Pros:
can easily be combined with existing STL algorithms, as well as for and while loops
can suspend (and resume) iteration
Cons:
requires polymorphism of attributes iterated over
Example:
class DataIterator;
class Data {
public:
friend class DataIterator;
Data(Point a, Point b, Point c): _one(a), _two(b), _three(c) {}
DataIterator begin();
DataIterator end();
private:
Point _one;
Point _two;
Point _three;
}; // class Data
class DataIterator:
public std::iterator<std::forward_iterator_tag, Point>
{
public:
struct BeginTag{};
struct EndTag{};
DataIterator(): _data(0), _member(0) {}
DataIterator(Data& data, BeginTag): _data(&data), _member(0) {}
DataIterator(Data& data, EndTag): _data(&data), _member(N) {}
reference operator*() const {
this->ensure_valid();
MemberPtr const ptr = Pointers[_member];
return _data->*ptr;
}
pointer operator->() const { return std::addressof(*(*this)); }
DataIterator& operator++() { this->ensure_valid(); ++_member; return *this; }
DataIterator operator++(int) { DataIterator tmp(*this); ++*this; return tmp; }
friend bool operator==(DataIterator const& left, DataIterator const& right) {
return left._data == right._data and left._member == right._member;
}
friend bool operator!=(DataIterator const& left, DataIterator const& right) {
return not (left == right);
}
private:
typedef Point Data::*MemberPtr;
static size_t const N = 3;
static MemberPtr const Pointers[N];
void ensure_valid() const { assert(_data and _member < N); }
Data* _data;
size_t _member;
}; // class DataIterator
//
// Implementation
//
DataIterator Data::begin() { return DataIterator(*this, DataIterator::BeginTag{}); }
DataIterator Data::end() { return DataIterator(*this, DataIterator::EndTag{}); }
size_t const DataIterator::N;
DataIterator::MemberPtr const DataIterator::Pointers[DataIterator::N] = {
&Data::_one, &Data::_two, &Data::_three
};
And in case you wonder: yes, it really works.
Using the visitation method, though, is easier.
Pros:
can easily accommodate variance in the attributes types iterated over
Cons:
cannot be combined with existing STL algorithms or existing loops
pretty difficult to suspend the iteration part-way
Example:
class Data {
public:
Data(Point a, Point b, Point c): _one(a), _two(b), _three(c) {}
template <typename F>
void apply(F&& f) {
f(_one);
f(_two);
f(_three);
}
private:
Point _one;
Point _two;
Point _three;
}; // class Data
And of course, it works too.
Do it like this:
class data{
public:
enum POINTS {LEFT=0,RIGHT,SOME_OTHER_POINT};
std::array<point,50> points; // or just point points[50];
}example;
And use it like this:
example.points[data::LEFT]=point{};
Then you can iterate over points array with standard techniques.
You can convert your current fields into:
private:
point left;
// ..
public:
point& left() { return points[LEFT]; }
// ..
where points might be an array of points (as in other answers), and LEFT is a constant index into array. This should allow for a relatively quick and painless transition, you will only have to add (), and compiler will output errors where to apply fixes.
Then you can convert your code to iterate your point values.
You can write a for each function without modifying your example like this:
template<class Func>
void for_each_point(example& e, Func&& f){
f(e.pt1);
f(e.pt2);
f(e.blah);
....
f(e.last_pt);
}
and then call it like:
for_each_point(exam, [&](point & pt){
std::cout<<pt.data<<"\n";
});
or do whatever in the body.
This function could also be a member variable, if you prefer.
Changing tye point storage to an array or std::array amd exposing begin and end or the array also works.
Finally, you could write a custom iterator that walks the points, but that is probably unwise.

Abstract iterator for underlying collections

So basically what I want to do is to have a pure virtual method returning an iterator to an arbitrary collection of a concrete type, e.g in pseudo code:
virtual Iterator<T> getIterator() const = 0;
The user of this class actually don't care what implementation the child class uses. It could be a set, vector, list, array etc.
I'm aware of the std::iterator class but I cant find a way to specify it correctly in order to work with a simple vector.
virtual std::iterator<std::random_access_iterator_tag,T> getIterator() const = 0;
myVector.begin() // compilation error in implementation
defining std::iterator with const T as type parameter hasn't worked too. I also tried leaving T and instead defining the pointer and reference types as const T* and const T&.
By taking a look at the std::vector implementation, I found out that std::vector::const_iterator actually derives from _Iterator012 deriving from _Iterator_base.
It really bugs me that there isn't any way to work with arbitrary collections in std.
Implementing my classes as templates like in <algorithm> is not an option for me due two reasons:
No control over the actual value type
I simply don't want to make my classes templates complicating my design a lot and making things less flexible.
The used type parameter T was just for demonstration, actually this is a concrete type.
Here's a basic and very rudimentary skeleton approach using type erasure. You'll have to fill in a lot of missing details, though!
#include <memory>
template <typename T>
class TEIterator
{
struct TEImplBase
{
virtual ~TEImplBase() { }
virtual std::unique_ptr<TEImplBase> clone() const = 0;
virtual void increment() = 0;
virtual T & getValue() = 0;
T * getPointer() { return std::addressof(getValue()); }
};
template <typename Iter>
struct TEImpl
{
Iter iter;
TEImpl(Iter i) : iter(i) { }
virtual T & getValue()
{ return *iter; }
virtual std::unique_ptr<TEImplBase> clone() const
{ return std::unique_ptr<TEImplBase>(new TEImpl<Iter>(*this)); }
virtual void increment()
{ ++iter; }
};
std::unique_ptr<TEImplBase> impl;
public:
template <typename T>
TEClass(T && x)
: impl(new TEImpl<typename std::decay<T>::type>(std::forward<T>(x)))
{
}
TEClass(TEClass && rhs) = default;
TEClass(TEClass const & rhs) : impl(rhs.impl.clone()) { }
TEIterator & operator++()
{
impl->increment();
return *this;
}
T & operator*() { return impl->getValue(); }
T * operator->() { return impl->getPointer(); }
};
Usage:
std::vector<int> v;
std::deque<int> dq;
TEIterator<int> a = v.begin(), b = dq.end();
If you want to use a virtual method, you cannot use an arbitrary return value. What you can do, is define a base class, which is a wrapper around iterators, and subclass from that wrapper class.
But even then, you must restrict yourself to the smallest common denominator, since there are several iterator classes in the C++ standard library.
So, AFAICS, such a method with arbitrary iterators isn't really feasible without using templates.