From 595b4e1a9b436a8190964dc41f79621400f5a6be Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Mon, 29 Mar 2021 14:13:46 +0200 Subject: [PATCH] QList: Satisfy contiguous_range requirements With C++20, there is a new iterator_category: contiguous_iterator, for containers whose elements are stored contiguously in memory. In Qt 6, QList satisfies this requirement. However, we still need to tell the standard machinery about it. Step one is to mark the iterators as contiguous_iterator; as that exists only in C++20, we have to ifdef accordingly. We also have to ensure that the iterators satisfy pointer_traits by defining element_type due to how contiguous_range is specified. As this runs afoul of LWG 3346, we check for known bad _GLIBCXX_RELEASE versions. Change-Id: I8c134544e694ba937e4d912393eb72fa75b49e3d Reviewed-by: Lars Knoll Reviewed-by: Giuseppe D'Angelo --- src/corelib/tools/qlist.h | 17 +++++++++++++++-- tests/auto/corelib/tools/qlist/tst_qlist.cpp | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 841deb02a1..61a02f795b 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -132,9 +132,16 @@ public: class iterator { T *i = nullptr; public: - using iterator_category = std::random_access_iterator_tag; using difference_type = qsizetype; using value_type = T; + // libstdc++ shipped with gcc < 11 does not have a fix for defect LWG 3346 +#if __cplusplus >= 202002L && (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE >= 11) + using iterator_category = std::contiguous_iterator_tag; +#else + using iterator_category = std::random_access_iterator_tag; +#endif + using element_type = value_type; + using pointer = T *; using reference = T &; @@ -167,9 +174,15 @@ public: class const_iterator { const T *i = nullptr; public: - using iterator_category = std::random_access_iterator_tag; using difference_type = qsizetype; using value_type = T; + // libstdc++ shipped with gcc < 11 does not have a fix for defect LWG 3346 +#if __cplusplus >= 202002L && (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE >= 11) + using iterator_category = std::contiguous_iterator_tag; +#else + using iterator_category = std::random_access_iterator_tag; +#endif + using element_type = const value_type; using pointer = const T *; using reference = const T &; diff --git a/tests/auto/corelib/tools/qlist/tst_qlist.cpp b/tests/auto/corelib/tools/qlist/tst_qlist.cpp index 96a1a35968..d6ff25b830 100644 --- a/tests/auto/corelib/tools/qlist/tst_qlist.cpp +++ b/tests/auto/corelib/tools/qlist/tst_qlist.cpp @@ -33,6 +33,26 @@ #include #include + +#if __cplusplus >= 202002L && (!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE >= 11) +# if __has_include() +# include +# if defined(__cpp_concepts) + static_assert(std::contiguous_iterator::iterator>); + static_assert(std::contiguous_iterator::const_iterator>); +# endif +# endif +# if __has_include() +# include +# if defined(__cpp_lib_ranges) + namespace rns = std::ranges; + + static_assert(rns::contiguous_range>); + static_assert(rns::contiguous_range>); +# endif +# endif +#endif + struct Movable { Movable(char input = 'j') : i(input)