How to access standard *this behaviour after overloading operator*? - c++

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.

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

Turning the next(), hasNext() iterator interface into begin(), end() interface

I have to use an external library I cannot change. This library among others can tokenize specially formatted files by its internal logic. The tokenizer offers an iterator interface for accessing tokens, which looks like the following simplified example:
class Tokenizer {
public:
/* ... */
Token token() const; // returns the current token
Token next() const; // returns the next token
bool hasNext() const; // returns 'true' if there are more tokens
/* ... */
};
I would like to implement an iterator wrapper for the presented Tokenizer which allows the use of standard algorithms library (std::copy_if, std::count, etc.). To be more specific, suffice if the iterator wrapper meets the requirements of input iterator.
My current trial looks like the following:
class TokenIterator {
public:
using iterator_category = std::input_iterator_tag;
using value_type = Token;
using difference_type = std::ptrdiff_t;
using pointer = const value_type*;
using reference = const value_type&;
explicit TokenIterator(Tokenizer& tokenizer) :
tokenizer(tokenizer) {
}
TokenIterator& operator++() {
tokenizer.next();
return *this;
}
value_type operator*() {
return tokenizer.token();
}
private:
Tokenizer& tokenizer;
};
I got stuck with implementation of functions like begin and end, equality comparator, etc. So, my questions are:
How can I construct a TokenIterator instance which indicates the end of the token sequence (i.e. hasNext() == false) and how can I compare it to another TokenIterator instance to decide whether they are same?
Is it a good approach if I return a value from the overload of operator*() instead of a reference?
First, I recommend taking a close look at http://www.boost.org/doc/libs/1_65_1/libs/iterator/doc/iterator_facade.html
I find that it vastly reduces the amount of boilerplate needed for code like this.
Then, you have to decide how you wish to represent an iterator that has reached the "end". One approach is to make a default constructed iterator be the "end" iterator. It contains no object and you must not increment or dereference it.
The "begin" iterator is then a non-default-constructed iterator. It has an object and you can dereference it. Incrementing this iterator simply checks hasNext(). If true, set the contained object to next(). If false, clear the contained object and make this iterator look like like a default constructed one.
There shouln't be any problems returning by value from operator*. Even if you assign to a reference, lifetime extension will keep the value around until the reference goes out of scope. That said, any code that assumes such references remain valid over multiple iterations WILL break, so stick to simple for (auto val : tokens) or for (auto& val : tokens).
By the suggestions of the accepted answer I successfully implemented the iterator wrapper I intended to do.
Here is an example implementation which corresponds to the example shown in the question:
class TokenIterator {
public:
using iterator_category = std::input_iterator_tag;
using value_type = Token;
using difference_type = std::ptrdiff_t;
using pointer = const value_type*;
using reference = const value_type&;
TokenIterator() : tokenizer(nullptr), token(value_type()) {
}
TokenIterator(Tokenizer& tokenizerToWrap) : TokenIterator() {
if(tokenizerToWrap.hasNext()) {
tokenizer = &tokenizerToWrap;
token = tokenizerToWrap.token();
}
}
TokenIterator(const TokenIterator& other) :
tokenizer(other.tokenizer), token(other.token) {
}
reference operator*() const {
assertTokenizer();
return token;
}
pointer operator->() const {
return &(operator*());
}
TokenIterator& operator++() {
assertTokenizer();
if(tokenizer->hasNext())
token = tokenizer->next();
else
*this = TokenIterator();
return *this;
}
TokenIterator operator++(int) {
TokenIterator previousState = *this;
operator++();
return previousState;
}
friend bool operator==(const TokenIterator& lhs, const TokenIterator& rhs) {
return lhs.tokenizer == rhs.tokenizer;
}
friend bool operator!=(const TokenIterator& lhs, const TokenIterator& rhs) {
return !(lhs == rhs);
}
private:
void assertTokenizer() const {
if(!tokenizer) throw std::out_of_range("iterator is out of range");
}
Tokenizer* tokenizer;
value_type token;
};
For the compatibility with the range-based for loop, here are the necessary begin() and end() functions:
TokenIterator begin(Tokenizer& tokenizerToWrap) {
return TokenIterator(tokenizerToWrap);
}
TokenIterator end(Tokenizer&) {
return TokenIterator();
}

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.

std::shared_ptr Iterator

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

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.