eepp
eepp

Reputation: 7585

In C++, is it okay to implement an iterator interface in which advancing invalidates the "current" element?

I'm designing a C++ interface which allows the user to iterate on objects decoded from a file. This decoding process is somewhat slow.

I'm considering an iterator interface for this, but I want to avoid any unnecessary copy, so I'm thinking about (user's side):

for (const auto& object : file) {
    // you can access the members of `object` here
    std::cout << object.whatever() << std::endl;

    // you can copy `object` here
    myObjectCopy = object;

    // you CANNOT do this because `object` changes
    // as soon as the iterator advances
    myObjectPtr = &object;
}

object in the previous usage example is a reference to an object internal to the iterator instance.

Is this wrong? What other idiomatic interfaces would you suggest here?

I thought about a stream interface (think std::istream), but AFAIK, the methods to read data also return copies (they extract characters).

Upvotes: 4

Views: 270

Answers (2)

Sam Varshavchik
Sam Varshavchik

Reputation: 118425

Sounds like what you're talking about is an input iterator.

Be sure to inherit your custom iterator class from std::iterator<std::input_iterator_tag, decoded_object_type>. A classical implementation is for operator* to cache the decoded object, and return the cached object if it's invoked a second time before operator++ gets invoked; and operator++ invoking operator* to make sure that the object gets decoded, if it's not already.

Upvotes: 7

John Zwinck
John Zwinck

Reputation: 249502

Yes, it's OK. An iostream is basically the same: if you iterate over the values you get from it, you can copy them, but you cannot hold a pointer to them after the stream or iterator on the stream is advanced.

Upvotes: 2

Related Questions