I solve the following problem: there is some file whose structure is a set of blocks. Each block has a header and body. The last block is marked with the corresponding identifier. To bypass the blocks in the file, I write my own iterator:
/** * @brief Single-pass input iterator. */ class BlockIterator : public std::iterator<std::input_iterator_tag, const DataBlock> { private: friend class FileReader; FileReader* reader; // Π’Π΅ΠΊΡΡΠΈΠΉ Π±Π»ΠΎΠΊ, Π½Π° ΠΊΠΎΡΠΎΡΡΠΉ ΡΠΊΠ°Π·ΡΠ²Π°Π΅Ρ ΠΈΡΠ΅ΡΠ°ΡΠΎΡ. std::unique_ptr<DataBlock> block; BlockIterator(FileReader* r, std::unique_ptr<DataBlock> b) noexcept : reader(r), block(std::move(b)) { /*NOP*/ }; public: BlockIterator& operator++() { auto nextBlockOffset = block->offset + block->headerSize + block->bodySize; block = reader->getBlockAt(nextBlockOffset); // ^^^ Π€ΡΠ½ΠΊΡΠΈΡ ΠΌΠΎΠΆΠ΅Ρ Π²ΡΠΊΠΈΠ΄ΡΠ²Π°ΡΡ ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅! return *this; } BlockIterator operator++(int) { auto retval = *this; ++(*this); return retval; } bool operator==(const BlockIterator& other) const { return reader == other.reader && block == other.block; } bool operator!=(const BlockIterator& other) const { return !(*this == other); } reference operator*() const { return *block; } }; When incrementing, the getBlockAt() function can throw an exception (for example, if the parsim is an invalid file). How in this case is better to do: is it necessary to guarantee the absence of exceptions when working with an iterator? If so, how to ensure the iterator is invalidated and an error is output?
std::iterator, you need to follow its ideology. An iterator assumes validity when pointing to existing data, and incorrect data (invalid file) is an exception for the iterator. An exception must throw an exception. Partly my opinion is confirmed by the fact that the iterators of the standard library are not declared as not generating exceptions. - user194374