iterator Overload Member Selection vs Indirection Operator
Asked Answered
Q

2

1

So in the interest of creating a Minimal. Complete, Verifiable Example I have created a toy iterator here (I know it's not perfect, it's just for the purposes of asking a question):

class foo : public iterator<input_iterator_tag, string> {
    string _foo;
    static const size_t _size = 13;
public:
    const string& operator*() { return _foo; }
    const foo& operator++() {
        _foo += '*';
        return *this;
    }
    const foo operator++(int) { 
        auto result = *this;
        _foo += '*';
        return result;
    }
    bool operator==(const foo& rhs) { return _foo.empty() != rhs._foo.empty() && _foo.size() % _size == rhs._foo.size() % _size; }
    bool operator!=(const foo& rhs) { return !operator==(rhs); }
};

I read that an InputIterator needs to have defined the Member Selection Operator. The Indirection Operator makes sense, but a Member Selection Operator is confusing to me here. How would an Member Selection Operator be implemented for foo?

Quadrilateral answered 12/5, 2016 at 15:24 Comment(1)
By the way, the prefix ++ operator should return foo& instead of const foo& or you won't be able to do ++(++i) - and it's missing the return statement.Landgravine
L
2
const string* operator->() const { return &_foo; }

Example usage:

foo i;
++i;
assert(i->length() == 1);

The way this works is that the compiler will generate repeated calls to operator-> until the return type is a raw pointer (so in this case just one call to foo::operator->), then do the regular member selection operation on that pointer.

Landgravine answered 12/5, 2016 at 15:50 Comment(0)
C
2

The operator->() should return a pointer type of the type the container holds that the iterator is used on. So if you have a container that holds a std::string then the iterator::operator-> should return a std::sting*. In your case since you derive from std::iterator you can use the pointer typedef for the return type.

Chindwin answered 12/5, 2016 at 15:48 Comment(1)
@DanielSchepler I was not sure if that was a mistake by the OP or not. They use std::string for the template parameter to iterator which makes iterator::pointer a std::string* and I believe the class should actually store the data member as pointer _foo;.Chindwin
L
2
const string* operator->() const { return &_foo; }

Example usage:

foo i;
++i;
assert(i->length() == 1);

The way this works is that the compiler will generate repeated calls to operator-> until the return type is a raw pointer (so in this case just one call to foo::operator->), then do the regular member selection operation on that pointer.

Landgravine answered 12/5, 2016 at 15:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.