From 1b559b25a625c44a882d63e7160122990cfe8541 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 24 Jan 2024 11:36:35 +0100 Subject: [PATCH] QSpan: make adl_begin() etc SFINAE-friendly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The definition of iterator_t, and, therefore, of is_compatible_range depends on this, otherwise say, 0, is being treated as a valid range and hits a hard error in adl_begin() when trying to call begin(int&). TIL: decltype(auto) does _not_ SFINAE. Fix by calculating the return type manually, re-enabing SFINAE. Pick-to: 6.6 Change-Id: Icacd70554f4050ecaeb396c9ae60bc4f21a220c9 Reviewed-by: MÃ¥rten Nordheim (cherry picked from commit 94e122c594a3697b98dcc99a9e332b0f5e816d2d) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/tools/qspan.h | 17 ++++++++++++++--- tests/auto/corelib/tools/qspan/tst_qspan.cpp | 3 +++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/corelib/tools/qspan.h b/src/corelib/tools/qspan.h index 5137416fafc..f72329d9d5f 100644 --- a/src/corelib/tools/qspan.h +++ b/src/corelib/tools/qspan.h @@ -76,14 +76,25 @@ using is_qualification_conversion = template constexpr inline bool is_qualification_conversion_v = is_qualification_conversion::value; +namespace AdlTester { +#define MAKE_ADL_TEST(what) \ + using std:: what; /* bring into scope */ \ + template using what ## _result = decltype( what (std::declval())); \ + /* end */ +MAKE_ADL_TEST(begin) +MAKE_ADL_TEST(data) +MAKE_ADL_TEST(size) +#undef MAKE_ADL_TEST +} + // Replacements for std::ranges::XXX(), but only bringing in ADL XXX()s, // not doing the extra work C++20 requires template -decltype(auto) adl_begin(Range &&r) { using std::begin; return begin(r); } +AdlTester::begin_result adl_begin(Range &&r) { using std::begin; return begin(r); } template -decltype(auto) adl_data(Range &&r) { using std::data; return data(r); } +AdlTester::data_result adl_data(Range &&r) { using std::data; return data(r); } template -decltype(auto) adl_size(Range &&r) { using std::size; return size(r); } +AdlTester::size_result adl_size(Range &&r) { using std::size; return size(r); } // Replacement for std::ranges::iterator_t (which depends on C++20 std::ranges::begin) // This one uses adl_begin() instead. diff --git a/tests/auto/corelib/tools/qspan/tst_qspan.cpp b/tests/auto/corelib/tools/qspan/tst_qspan.cpp index d994484c7b3..c1bd780cb68 100644 --- a/tests/auto/corelib/tools/qspan/tst_qspan.cpp +++ b/tests/auto/corelib/tools/qspan/tst_qspan.cpp @@ -96,6 +96,9 @@ static_assert(!std::is_convertible_v, std::span>); static_assert(!std::is_convertible_v, std::span>); #endif // __cpp_lib_span +// Spans don't convert from nonsense: +static_assert(!std::is_constructible_v, int&&>); + class tst_QSpan : public QObject { Q_OBJECT