77
88#include < doctest/doctest.h>
99
10+ #include < optional>
11+
1012namespace {
1113using power_grid_model::Idx;
1214using power_grid_model::IdxRange;
1315using power_grid_model::IdxVector;
1416using power_grid_model::IteratorFacade;
1517using power_grid_model::detail::iterator_facadeable_c;
1618
17- template <typename UnderlyingType> class BaseTestIterator : public IteratorFacade {
19+ enum class IteratorFacadeableCalls : Idx {
20+ none = 0 ,
21+ dereference = 1 ,
22+ advance = 2 ,
23+ distance_to = 3 ,
24+ increment = 4 ,
25+ decrement = 5 ,
26+ };
27+
28+ struct without_increment_decrement_t {};
29+ struct with_increment_decrement_t {};
30+
31+ template <typename T>
32+ concept advance_type_c = std::same_as<T, without_increment_decrement_t > || std::same_as<T, with_increment_decrement_t >;
33+
34+ template <advance_type_c advance_type_t , typename UnderlyingType> class BaseTestIterator : public IteratorFacade {
35+ friend class IteratorFacade ;
36+
1837 public:
1938 using underlying = UnderlyingType;
2039
@@ -23,38 +42,84 @@ template <typename UnderlyingType> class BaseTestIterator : public IteratorFacad
2342 using pointer = underlying::pointer;
2443 using reference = underlying::reference;
2544
45+ static constexpr auto increment_style = std::same_as<advance_type_t , with_increment_decrement_t >
46+ ? IteratorFacadeableCalls::increment
47+ : IteratorFacadeableCalls::advance;
48+ static constexpr auto decrement_style = std::same_as<advance_type_t , with_increment_decrement_t >
49+ ? IteratorFacadeableCalls::decrement
50+ : IteratorFacadeableCalls::advance;
51+
52+ mutable std::optional<IteratorFacadeableCalls> last_call;
53+
2654 constexpr BaseTestIterator (std::remove_cvref_t <underlying> it) : IteratorFacade{*this }, it_{std::move (it)} {}
2755
28- constexpr auto operator *() -> reference { return *it_; }
29- constexpr auto operator *() const -> std::add_lvalue_reference_t <std::add_const_t <value_type>> { return *it_; }
56+ constexpr auto operator *() -> reference {
57+ last_call = IteratorFacadeableCalls::dereference;
58+ return *it_;
59+ }
60+ constexpr auto operator *() const -> std::add_lvalue_reference_t <std::add_const_t <value_type>> {
61+ last_call = IteratorFacadeableCalls::dereference;
62+ return *it_;
63+ }
3064
3165 friend constexpr auto operator <=>(BaseTestIterator const & first,
3266 BaseTestIterator const & second) -> std::strong_ordering {
67+ first.last_call = IteratorFacadeableCalls::distance_to;
3368 return *first.it_ <=> *second.it_ ;
3469 }
3570
36- constexpr auto operator +=(difference_type n) -> std::add_lvalue_reference_t <BaseTestIterator> {
71+ constexpr decltype (auto ) operator+=(difference_type n) {
72+ last_call = IteratorFacadeableCalls::advance;
3773 it_ += n;
3874 return *this ;
3975 }
4076 friend constexpr auto operator -(BaseTestIterator const & first, BaseTestIterator const & second) -> difference_type {
77+ first.last_call = IteratorFacadeableCalls::distance_to;
4178 return first.it_ - second.it_ ;
4279 }
4380
4481 private:
4582 underlying it_;
83+
84+ constexpr void increment ()
85+ requires std::same_as<advance_type_t, with_increment_decrement_t>
86+ {
87+ last_call = IteratorFacadeableCalls::increment;
88+ ++it_;
89+ }
90+ constexpr void decrement ()
91+ requires std::same_as<advance_type_t, with_increment_decrement_t>
92+ {
93+ last_call = IteratorFacadeableCalls::decrement;
94+ --it_;
95+ }
4696};
4797
48- using TestIdxVectorIterator = BaseTestIterator<typename IdxVector::iterator>;
49- using TestIdxVectorConstIterator = BaseTestIterator<typename IdxVector::const_iterator>;
98+ using TestIdxVectorIterator = BaseTestIterator<without_increment_decrement_t , typename IdxVector::iterator>;
99+ using TestIdxVectorConstIterator = BaseTestIterator<without_increment_decrement_t , typename IdxVector::const_iterator>;
100+ using TestIdxVectorIteratorWithIncDec = BaseTestIterator<with_increment_decrement_t , typename IdxVector::iterator>;
101+ using TestIdxVectorConstIteratorWithIncDec =
102+ BaseTestIterator<with_increment_decrement_t , typename IdxVector::const_iterator>;
50103
51104static_assert (iterator_facadeable_c<TestIdxVectorIterator>);
52105static_assert (iterator_facadeable_c<TestIdxVectorConstIterator>);
106+ static_assert (iterator_facadeable_c<TestIdxVectorIteratorWithIncDec>);
107+ static_assert (iterator_facadeable_c<TestIdxVectorConstIteratorWithIncDec>);
108+
53109static_assert (std::constructible_from<IteratorFacade, TestIdxVectorIterator>);
54110static_assert (std::constructible_from<IteratorFacade, TestIdxVectorConstIterator>);
111+ static_assert (std::constructible_from<IteratorFacade, TestIdxVectorIteratorWithIncDec>);
112+ static_assert (std::constructible_from<IteratorFacade, TestIdxVectorConstIteratorWithIncDec>);
113+
55114} // namespace
56115
57- TEST_CASE_TEMPLATE (" Test IteratorFacade" , T, TestIdxVectorIterator, TestIdxVectorConstIterator) {
116+ TYPE_TO_STRING_AS (" TestIdxVectorIterator" , TestIdxVectorIterator);
117+ TYPE_TO_STRING_AS (" TestIdxVectorConstIterator" , TestIdxVectorConstIterator);
118+ TYPE_TO_STRING_AS (" TestIdxVectorIteratorWithIncDec" , TestIdxVectorIteratorWithIncDec);
119+ TYPE_TO_STRING_AS (" TestIdxVectorConstIteratorWithIncDec" , TestIdxVectorConstIteratorWithIncDec);
120+
121+ TEST_CASE_TEMPLATE (" Test IteratorFacade" , T, TestIdxVectorIterator, TestIdxVectorConstIterator,
122+ TestIdxVectorIteratorWithIncDec, TestIdxVectorConstIteratorWithIncDec) {
58123 using TestIterator = T;
59124
60125 auto vec = IdxRange{40 } | std::ranges::to<IdxVector>();
@@ -63,10 +128,10 @@ TEST_CASE_TEMPLATE("Test IteratorFacade", T, TestIdxVectorIterator, TestIdxVecto
63128 auto it = TestIterator{vec.begin () + 5 };
64129 CHECK (*it == 5 );
65130 CHECK (*(++it) == 6 );
66- CHECK (*it++ == 6 );
131+ CHECK (*( it++) == 6 );
67132 CHECK (*it == 7 );
68133 CHECK (*(--it) == 6 );
69- CHECK (*it-- == 6 );
134+ CHECK (*( it--) == 6 );
70135 CHECK (*it == 5 );
71136 it += 3 ;
72137 CHECK (*it == 8 );
@@ -103,4 +168,28 @@ TEST_CASE_TEMPLATE("Test IteratorFacade", T, TestIdxVectorIterator, TestIdxVecto
103168 CHECK (vec[5 ] == 42 );
104169 }
105170 }
171+ SUBCASE (" Incremented/Decremented calls" ) {
172+ auto it = TestIterator{vec.begin () + 5 };
173+ REQUIRE (!it.last_call .has_value ());
174+
175+ ++it;
176+ REQUIRE (it.last_call .has_value ());
177+ CHECK (it.last_call .value () == TestIterator::increment_style);
178+ it.last_call .reset ();
179+
180+ it++;
181+ REQUIRE (it.last_call .has_value ());
182+ CHECK (it.last_call .value () == TestIterator::increment_style);
183+ it.last_call .reset ();
184+
185+ --it;
186+ REQUIRE (it.last_call .has_value ());
187+ CHECK (it.last_call .value () == TestIterator::decrement_style);
188+ it.last_call .reset ();
189+
190+ it--;
191+ REQUIRE (it.last_call .has_value ());
192+ CHECK (it.last_call .value () == TestIterator::decrement_style);
193+ it.last_call .reset ();
194+ }
106195}
0 commit comments