Skip to content

Commit

Permalink
QSpan: make adl_begin() etc SFINAE-friendly
Browse files Browse the repository at this point in the history
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.

Manual conflict resolutions:
 - qspan.h -> qspan_p.h

Change-Id: Icacd70554f4050ecaeb396c9ae60bc4f21a220c9
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
(cherry picked from commit 94e122c)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
(cherry picked from commit 1b559b2)
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
  • Loading branch information
marcmutz committed Feb 1, 2024
1 parent 2e1a258 commit 6b15e0c
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 3 deletions.
17 changes: 14 additions & 3 deletions src/corelib/tools/qspan_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,25 @@ using is_qualification_conversion =
template <typename From, typename To>
constexpr inline bool is_qualification_conversion_v = is_qualification_conversion<From, To>::value;

namespace AdlTester {
#define MAKE_ADL_TEST(what) \
using std:: what; /* bring into scope */ \
template <typename T> using what ## _result = decltype( what (std::declval<T&&>())); \
/* 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 <typename Range>
decltype(auto) adl_begin(Range &&r) { using std::begin; return begin(r); }
AdlTester::begin_result<Range> adl_begin(Range &&r) { using std::begin; return begin(r); }
template <typename Range>
decltype(auto) adl_data(Range &&r) { using std::data; return data(r); }
AdlTester::data_result<Range> adl_data(Range &&r) { using std::data; return data(r); }
template <typename Range>
decltype(auto) adl_size(Range &&r) { using std::size; return size(r); }
AdlTester::size_result<Range> 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.
Expand Down
3 changes: 3 additions & 0 deletions tests/auto/corelib/tools/qspan/tst_qspan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ static_assert(!std::is_convertible_v<QSpan<const int, 42>, std::span<int, 42>>);
static_assert(!std::is_convertible_v<QSpan<const int, 0>, std::span<int, 0>>);
#endif // __cpp_lib_span

// Spans don't convert from nonsense:
static_assert(!std::is_constructible_v<QSpan<const int>, int&&>);

class tst_QSpan : public QObject
{
Q_OBJECT
Expand Down

0 comments on commit 6b15e0c

Please sign in to comment.