From f5cee49c71e7c0e805695b03e8af533783789762 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 11 Nov 2024 06:49:11 +0100 Subject: [PATCH] Add test for iterators with const T as the value_type --- .../SelfTest/UsageTests/Compilation.tests.cpp | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/tests/SelfTest/UsageTests/Compilation.tests.cpp b/tests/SelfTest/UsageTests/Compilation.tests.cpp index a7fbf08fc9..7a6a1f252b 100644 --- a/tests/SelfTest/UsageTests/Compilation.tests.cpp +++ b/tests/SelfTest/UsageTests/Compilation.tests.cpp @@ -8,6 +8,7 @@ #include +#include #include // Setup for #1403 -- look for global overloads of operator << for classes @@ -34,6 +35,7 @@ static std::ostream& operator<<(std::ostream& out, foo::helper_1403 const&) { /////////////////////////////// #include +#include #include #include @@ -467,3 +469,57 @@ TEST_CASE( "Comparing const std::weak_ordering instances must compile", REQUIRE( plain_ordering_1 == const_ordering_1 ); } #endif + +// Reproduce issue with yaml-cpp iterators, where the `const_iterator` +// for Node type has `const T` as the value_type. This is wrong for +// multitude of reasons, but there might be other libraries in the wild +// that share this issue, and the workaround needed to support +// `from_range(iter, iter)` helper with those libraries is easy enough. +class HasBadIterator { + std::array m_arr{}; + +public: + class iterator { + const int* m_ptr = nullptr; + + public: + iterator( const int* ptr ): m_ptr( ptr ) {} + + using difference_type = std::ptrdiff_t; + using value_type = const int; + using pointer = const int*; + using reference = const int&; + using iterator_category = std::input_iterator_tag; + + iterator& operator++() { + ++m_ptr; + return *this; + } + + iterator operator++( int ) { + auto ret( *this ); + ++( *this ); + return ret; + } + + friend bool operator==( iterator lhs, iterator rhs ) { + return lhs.m_ptr == rhs.m_ptr; + } + friend bool operator!=( iterator lhs, iterator rhs ) { + return !( lhs == rhs ); + } + + int operator*() const { return *m_ptr; } + }; + + iterator cbegin() const { return { m_arr.data() }; } + iterator cend() const { return { m_arr.data() + m_arr.size() }; } +}; + +TEST_CASE("from_range(iter, iter) supports const_iterators", "[generators][from-range][approvals]") { + using namespace Catch::Generators; + + HasBadIterator data; + auto gen = from_range(data.cbegin(), data.cend()); + (void)gen; +}