std::shared_ptr Iterator - c++

I have an iterator which iterates over a std::shared_ptr. So operator++ points the internally stored shared pointer to the next item.
template<class IT>
class MyIterator
{
public:
...
MyIterator& operator++()
{
_i = ... // Call factory
return *this;
}
private:
std::shared_ptr<IT> _i;
};
How should I implement the operator*() and operator->() operators?
How should I test if the iterator is pointing to NULL, i.e. if the internal shared pointer is pointing to NULL.

You should define under what circumstances users are permitted to deference an instance of your class. Usually this is "anything other than an end iterator or an uninitialized iterator".
Then you should ensure that _i never contains a null pointer for an instance that can be dereferenced.
This means there is no need for a check, because the user is not permitted to call operator* or operator-> in that circumstance. You could add one for debugging, for example: assert(_i.get());.
You don't specify what the value_type is of your iterator, but assuming that it is IT, you can implement:
IT &operator*() { return *_i; }
shared_ptr<IT> operator->() { return _i; }
// or
IT *operator->() { return _i.get(); }

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;
};

How to access standard *this behaviour after overloading operator*?

I'm writing a wrapper for an iterator, and trying to make it behave just like the contained iterator.
For this, it requires to overload both operator* and operator++, but this poses the following problem:
//Typedefs to make below code easier to read
typedef std::map::const_iterator<std::string, SomeClass> iteratorAlias;
typedef std::pair<const std::string, SomeClass> mapPairAlias;
class IteratorWrapper
{
iteratorAlias iterator;
/*Other code omitted*/
mapPairAlias& operator*()
{
return *iterator;
}
const mapPairAlias& operator*() const
{
return *iterator;
}
IteratorWrapper& operator++()
{
++this->iterator;
return *this;
}
IteratorWrapper operator++(int)
{
IteratorWrapper copy(*this);
++(*this);
return copy;
}
};
In both operator++ functions, this needs to be dereferenced. But it looks like that would result in getting the mapPairAlias from the overloaded function, in stead of the IteratorWrapper.
How should this issue be resolved? The STL iterators handle both functions just fine, so presumably there is a way.
this is a raw pointer to the current instance
*this is a reference to the current instance
**this is syntactic sugar for this->operator*()
So the issue you described does not exist, *this will do what you want just fine.

redifining operators for iterator class c

I faced a problem of overloading the ->() operator while implementing the Iterator class. How should this operator be overloaded?
class iterator
{
private:
pair<Key_t, Val_t> p;
public:
iterator()
{
}
iterator(const iterator &i)
{
p = i.p;
}
iterator(Key_t key, Val_t v)
{
p = make_pair(key,v);
}
pair<const Key_t,Val_t>& operator *() const
{
return p;
}
iterator& operator = (const iterator &iter)
{
this->p = iter;
return *this;
}
};
tried this way unsuccessfully
&(pair<const Key_t,Val_t>&) operator ->() const
{
return &(**this);
}
This whole approach looks wrong.
An iterator isn't supposed to contain a value, it's supposed to contain at least
The information necessary to locate a value inside the container.
Information necessary to traverse to the next element within the container.
By storing a value inside the iterator, you cause unnecessary copies and lose the ability to update the container (change the value, remove the element from the container, etc).
For example, an iterator for a std::vector-like container might store a handle to the container and the index (offset) to the current item.
The only time an iterator would have a value itself is when you're implementing a generator that isn't actually associated with a container.

How to define the type of a member of an iterator class to work with STL container methods?

I wish to define an iterator class over a vector, and how can its private member p match the return type of std::vector::begin()?
class A{
struct element{
...
}
class e_iterator {
e_iterator() : p()
...
private:
element* p;
};
e_iterator e_begin() const{
e_iterator Iter;
Iter.p = e_.begin(); // error
return Iter;
}
std::vector<element> e_;
}
I receive an error with element* p:
error: cannot convert 'std::vector<element, std::allocator<element>>::const_iterator' to 'element*' in assignment
With what you've given, the most I can suggest is changing p to:
std::vector<element>::const_iterator p;
The simple fact is that a std::vector iterator is not a pointer (probably). It is an unspecified type that behaves like a pointer - it meets the requirements of a Random Access Iterator.
When you call begin() on a non-const container, you get an iterator type. When you call it on a const iterator, you get a const_iterator type. Since your a_begin member function is marked const and e_ appears to be a std::vector<element> member of your class, e_ is transitively const, so calling begin() on it will also get you a const_iterator.
But it's quite hard to tell exactly what you're trying to do here and whether this is the right way to go about it.
Either change element* p to const element* p in your iterator class or remove the const qualifier from your e_begin() method.
Or provide both const/non-const iterator. I also suggest to initialize the pointer in the iterator constructor:
template <bool isconst>
class e_iterator_ {
public:
typedef std::conditional<isconst, const element*, element*>::type elementptr;
e_iterator_(elementptr e) : p(e)
...
private:
elementptr p;
};
typedef e_iterator_<true> const_e_iterator;
typedef e_iterator_<false> e_iterator;
Then you could use the data() member method of std::vector to directly access the underlying array of the vector.
e_iterator e_begin() const{
const_e_iterator Iter(e_.data());
return Iter;
}
Hope this helps.

Semantic of -> operator in lists (and in general C++)

My current assignment is writing a list with iterators. The list isn't being a problem so much as creating the iterator class is.
From a couple of sources I've seen that I have two operators to define in my iterator class: operator* and operator->.
Great so far! Supposing my iterator structure is so
// Nested class of List
class _Iter
{
private:
ListElem *pCurr;
const List *pList;
public:
_Iter(ListElem *pCurr, const List *list)
: pCurr_(pCurr), pList(list)
{}
T& operator*() { return pCurr_->data; }
T* operator->() { return &**this; }
};
with ListElem being
// Nested struct of List
struct ListElem
{
T data;
ListElem *next;
ListElem *prev;
};
I can see I'm doing something massively wrong (as double dereferencing of this would lead to a &(*pCurr_->data), which is not dereferencable.
My main problem is not understanding what -> is actually supposed to do in this case. Should it grant the user access to the ListElem class? If that's the case, why can't I just write
ListElem *operator->() { return pCurr_; }
instead of returning a pointer? My understanding of these two operators as used in my list (and hopefully STL lists) is that:
operator*() // Return data pointed to by iterator; pCurr_->data;
operator->() // Grant access to data-holding structure; pCurr;
Is this correct, or what am I not getting? (And does -> have a proper name?)
Whatever you do, (*something).somethingElse should be equivalent to something->somethingElse. The latter is just a short syntax for the former. Therefore,
T& operator*() { return pCurr_->data; }
T* operator->() { return &**this; }
is fine because *this just dereferences this which has the type _Iter*, not _Iter, so no operator*() call is done. Then you dereference *this, so you get pCurr->data, then you take its address, so you get &pCurr->data. But it would be much clearer to just write:
T& operator*() { return pCurr_->data; }
T* operator->() { return &pCurr->data; }
Now, this
ListElem *operator->() { return pCurr_; }
is wrong because if operator*() returns T&, operator->() should return T*, that's what it was designed for. If you really want to grant access to ListItem instead of its data (which may or may not make sense depending on the design, but in your case it looks like it doesn't), then you should also redefine operator*() to get this:
ListElem& operator*() { return *pCurr_; }
ListElem *operator->() { return pCurr_; }
Note that it is not a language requirement, it is just how you design your class to avoid confusing interface.
Your main guideline should be that
(*iter).hello();
iter->hello();
should both do the same thing. That's what the user expects. Returning ListElem gives nothing to the user. The user shouldn't even know the details of the implementation of ListElem.
operator-> gives a pointer to the object pointed to by the iterator, in this case (apparently) pCurr_->data.
T *operator->() { return &(pCurr_->data); }
It should return the address of the object returned by operator*() as a value or reference.
T &operator*() { return pCurr_->data; }
// or
T &operator*() { return *operator->(); }
operator->() exists to implement -> with iterators (with the behavior it has for pointers) and is necessary because operator* may return an object by value instead of by reference.
Note that you don't need to store a pointer to the List in the iterator to obtain the functionality required.