From 47a65de3493a7df70d8daaea829dce9ac421a652 Mon Sep 17 00:00:00 2001 From: Aries Moczar Date: Fri, 24 Apr 2026 19:19:56 +0200 Subject: [PATCH 1/3] Added additional operator overloads '--', '*' and '->' for ChannelList::Iterator and ChannelList::ConstIterator. Also added global operator overloads '==' and '!=' for Iterator class. (issue #1325) Signed-off-by: Aries Moczar --- src/lib/OpenEXR/ImfChannelList.h | 92 ++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/src/lib/OpenEXR/ImfChannelList.h b/src/lib/OpenEXR/ImfChannelList.h index 6175746189..485f333dc5 100644 --- a/src/lib/OpenEXR/ImfChannelList.h +++ b/src/lib/OpenEXR/ImfChannelList.h @@ -264,6 +264,17 @@ class IMF_EXPORT_TYPE ChannelList::Iterator IMF_EXPORT Iterator operator++ (int); + IMF_EXPORT + Iterator& operator-- (); + IMF_EXPORT + Iterator operator-- (int); + + IMF_EXPORT + Channel& operator* () const; + + IMF_EXPORT + Channel* operator-> () const; + IMF_EXPORT const char* name () const; IMF_EXPORT @@ -271,6 +282,8 @@ class IMF_EXPORT_TYPE ChannelList::Iterator private: friend class ChannelList::ConstIterator; + friend bool operator== (Iterator&, Iterator&); + friend bool operator!= (Iterator&, Iterator&); ChannelList::ChannelMap::iterator _i; }; @@ -290,6 +303,17 @@ class IMF_EXPORT_TYPE ChannelList::ConstIterator IMF_EXPORT ConstIterator operator++ (int); + IMF_EXPORT + ConstIterator& operator-- (); + IMF_EXPORT + ConstIterator operator-- (int); + + IMF_EXPORT + const Channel& operator* () const; + + IMF_EXPORT + const Channel* operator-> () const; + IMF_EXPORT const char* name () const; IMF_EXPORT @@ -333,6 +357,33 @@ ChannelList::Iterator::operator++ (int) return tmp; } +inline ChannelList::Iterator& +ChannelList::Iterator::operator-- () +{ + --_i; + return *this; +} + +inline ChannelList::Iterator +ChannelList::Iterator::operator-- (int) +{ + Iterator tmp = *this; + --_i; + return tmp; +} + +inline Channel& +ChannelList::Iterator::operator* () const +{ + return _i->second; +} + +inline Channel* +ChannelList::Iterator::operator-> () const +{ + return &_i->second; +} + inline const char* ChannelList::Iterator::name () const { @@ -345,6 +396,20 @@ ChannelList::Iterator::channel () const return _i->second; } +inline bool +operator== ( + ChannelList::Iterator& x, ChannelList::Iterator& y) +{ + return x._i == y._i; +} + +inline bool +operator!= ( + ChannelList::Iterator& x, ChannelList::Iterator& y) +{ + return !(x == y); +} + inline ChannelList::ConstIterator::ConstIterator () : _i () { // empty @@ -379,6 +444,33 @@ ChannelList::ConstIterator::operator++ (int) return tmp; } +inline ChannelList::ConstIterator& +ChannelList::ConstIterator::operator-- () +{ + --_i; + return *this; +} + +inline ChannelList::ConstIterator +ChannelList::ConstIterator::operator-- (int) +{ + ConstIterator tmp = *this; + --_i; + return tmp; +} + +inline const Channel& +ChannelList::ConstIterator::operator* () const +{ + return _i->second; +} + +inline const Channel* +ChannelList::ConstIterator::operator-> () const +{ + return &_i->second; +} + inline const char* ChannelList::ConstIterator::name () const { From 2041f641a123358ed4c9adc84855accd7d1182cf Mon Sep 17 00:00:00 2001 From: Aries Moczar Date: Sun, 26 Apr 2026 10:37:21 +0200 Subject: [PATCH 2/3] Added '==' and '!=' overloads for mixed Iterator and ConstIterator comparisons. Added Iterator and ConstIterator traits. Signed-off-by: Aries Moczar --- src/lib/OpenEXR/ImfChannelList.h | 105 +++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 27 deletions(-) diff --git a/src/lib/OpenEXR/ImfChannelList.h b/src/lib/OpenEXR/ImfChannelList.h index 485f333dc5..c9d6fef055 100644 --- a/src/lib/OpenEXR/ImfChannelList.h +++ b/src/lib/OpenEXR/ImfChannelList.h @@ -254,6 +254,12 @@ class IMF_EXPORT_TYPE ChannelList class IMF_EXPORT_TYPE ChannelList::Iterator { public: + using iterator_category = std::bidirectional_iterator_tag; + using value_type = Channel; + using difference_type = std::ptrdiff_t; + using pointer = Channel*; + using reference = Channel&; + IMF_EXPORT Iterator (); IMF_EXPORT @@ -270,20 +276,26 @@ class IMF_EXPORT_TYPE ChannelList::Iterator Iterator operator-- (int); IMF_EXPORT - Channel& operator* () const; + reference operator* () const; IMF_EXPORT - Channel* operator-> () const; + pointer operator-> () const; IMF_EXPORT const char* name () const; IMF_EXPORT - Channel& channel () const; + reference channel () const; private: friend class ChannelList::ConstIterator; + friend bool operator== (Iterator&, Iterator&); + friend bool operator== (Iterator&, const ConstIterator&); + friend bool operator== (const ConstIterator&, Iterator&); + friend bool operator!= (Iterator&, Iterator&); + friend bool operator!= (Iterator&, const ConstIterator&); + friend bool operator!= (const ConstIterator&, Iterator&); ChannelList::ChannelMap::iterator _i; }; @@ -291,6 +303,12 @@ class IMF_EXPORT_TYPE ChannelList::Iterator class IMF_EXPORT_TYPE ChannelList::ConstIterator { public: + using iterator_category = std::bidirectional_iterator_tag; + using value_type = Channel; + using difference_type = std::ptrdiff_t; + using pointer = const Channel*; + using reference = const Channel&; + IMF_EXPORT ConstIterator (); IMF_EXPORT @@ -309,19 +327,24 @@ class IMF_EXPORT_TYPE ChannelList::ConstIterator ConstIterator operator-- (int); IMF_EXPORT - const Channel& operator* () const; + reference operator* () const; IMF_EXPORT - const Channel* operator-> () const; + pointer operator-> () const; IMF_EXPORT const char* name () const; IMF_EXPORT - const Channel& channel () const; + reference channel () const; private: friend bool operator== (const ConstIterator&, const ConstIterator&); + friend bool operator== (Iterator&, const ConstIterator&); + friend bool operator== (const ConstIterator&, Iterator&); + friend bool operator!= (const ConstIterator&, const ConstIterator&); + friend bool operator!= (Iterator&, const ConstIterator&); + friend bool operator!= (const ConstIterator&, Iterator&); ChannelList::ChannelMap::const_iterator _i; }; @@ -372,13 +395,13 @@ ChannelList::Iterator::operator-- (int) return tmp; } -inline Channel& +inline ChannelList::Iterator::reference ChannelList::Iterator::operator* () const { return _i->second; } -inline Channel* +inline ChannelList::Iterator::pointer ChannelList::Iterator::operator-> () const { return &_i->second; @@ -390,26 +413,12 @@ ChannelList::Iterator::name () const return *_i->first; } -inline Channel& +inline ChannelList::Iterator::reference ChannelList::Iterator::channel () const { return _i->second; } -inline bool -operator== ( - ChannelList::Iterator& x, ChannelList::Iterator& y) -{ - return x._i == y._i; -} - -inline bool -operator!= ( - ChannelList::Iterator& x, ChannelList::Iterator& y) -{ - return !(x == y); -} - inline ChannelList::ConstIterator::ConstIterator () : _i () { // empty @@ -459,13 +468,13 @@ ChannelList::ConstIterator::operator-- (int) return tmp; } -inline const Channel& +inline ChannelList::ConstIterator::reference ChannelList::ConstIterator::operator* () const { return _i->second; } -inline const Channel* +inline ChannelList::ConstIterator::pointer ChannelList::ConstIterator::operator-> () const { return &_i->second; @@ -477,12 +486,19 @@ ChannelList::ConstIterator::name () const return *_i->first; } -inline const Channel& +inline ChannelList::ConstIterator::reference ChannelList::ConstIterator::channel () const { return _i->second; } +inline bool +operator== ( + ChannelList::Iterator& x, ChannelList::Iterator& y) +{ + return x._i == y._i; +} + inline bool operator== ( const ChannelList::ConstIterator& x, const ChannelList::ConstIterator& y) @@ -490,11 +506,46 @@ operator== ( return x._i == y._i; } +inline bool +operator== ( + ChannelList::Iterator& x, const ChannelList::ConstIterator& y) +{ + return x._i == y._i; +} + +inline bool +operator== ( + const ChannelList::ConstIterator& x, ChannelList::Iterator& y) +{ + return x._i == y._i; +} + +inline bool +operator!= ( + ChannelList::Iterator& x, ChannelList::Iterator& y) +{ + return !(x._i == y._i); +} + inline bool operator!= ( const ChannelList::ConstIterator& x, const ChannelList::ConstIterator& y) { - return !(x == y); + return !(x._i == y._i); +} + +inline bool +operator!= ( + ChannelList::Iterator& x, const ChannelList::ConstIterator& y) +{ + return !(x._i == y._i); +} + +inline bool +operator!= ( + const ChannelList::ConstIterator& x, ChannelList::Iterator& y) +{ + return !(x._i == y,_i); } OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT From 652aa0ca7e540e9818d65308fc863b3b01f1115e Mon Sep 17 00:00:00 2001 From: Aries Moczar Date: Wed, 29 Apr 2026 18:24:59 +0200 Subject: [PATCH 3/3] Added test to testChannels unit-test to verify functionality of ChannelList::Iterator/ConstIterator Signed-off-by: Aries Moczar --- src/lib/OpenEXR/ImfChannelList.h | 2 +- src/test/OpenEXRTest/testChannels.cpp | 69 +++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/src/lib/OpenEXR/ImfChannelList.h b/src/lib/OpenEXR/ImfChannelList.h index c9d6fef055..a0415b02fa 100644 --- a/src/lib/OpenEXR/ImfChannelList.h +++ b/src/lib/OpenEXR/ImfChannelList.h @@ -545,7 +545,7 @@ inline bool operator!= ( const ChannelList::ConstIterator& x, ChannelList::Iterator& y) { - return !(x._i == y,_i); + return !(x._i == y._i); } OPENEXR_IMF_INTERNAL_NAMESPACE_HEADER_EXIT diff --git a/src/test/OpenEXRTest/testChannels.cpp b/src/test/OpenEXRTest/testChannels.cpp index b68a861801..8c0fa075b3 100644 --- a/src/test/OpenEXRTest/testChannels.cpp +++ b/src/test/OpenEXRTest/testChannels.cpp @@ -218,6 +218,71 @@ writeRead ( cout << endl; } +void +verifyIterators(void) +{ + ChannelList l1; + + l1.insert("A", Channel(HALF)); + l1.insert("B", Channel(HALF)); + l1.insert("C", Channel(HALF)); + + ChannelList::Iterator it1 = l1.begin(); + ChannelList::ConstIterator cit1 = l1.begin(); + + ChannelList::Iterator it2 = l1.end(); + ChannelList::ConstIterator cit2 = l1.end(); + + // Test global '!=' overloads + assert(it1 != it2); + assert(it1 != cit2); + assert(cit1 != it2); + assert(cit1 != cit2); + + // Test global '==' overloads + assert(it1 == it1); + assert(it1 == cit1); + assert(cit1 == it1); + assert(cit1 == cit1); + + // Test post/pre '++' overloads + it1++; + ++it1; + cit1++; + ++cit1; + + // Test post/pre '--' overloads + it1--; + --it1; + cit1--; + --cit1; + + assert(it1 == l1.begin()); + assert(cit1 == l1.begin()); + + while (it1 != l1.end()) + { + + // Test '*' overloads + Channel& c = *it1; + const Channel& cc = *cit1; + assert(c.type == HALF); + assert(cc.type == HALF); + + // Test '->' overload + assert(it1->type == HALF); + assert(cit1->type == HALF); + + // Test pre/post '++' overloads + it1++; + cit1++; + + } + + assert(it1 == l1.end()); + assert(cit1 == l1.end()); +} + } // namespace void @@ -225,6 +290,10 @@ testChannels (const std::string& tempDir) { try { + cout << "Testing ChannelList Iterator behavior" << endl; + + verifyIterators (); + cout << "Testing filling of missing channels" << endl; const int W = 117;