diff --git a/src/corelib/tools/qspan_p.h b/src/corelib/tools/qspan_p.h index f9de3ee4119..b3d6c13a708 100644 --- a/src/corelib/tools/qspan_p.h +++ b/src/corelib/tools/qspan_p.h @@ -37,6 +37,22 @@ namespace q20 { template class QSpan; +QT_BEGIN_INCLUDE_NAMESPACE +#ifdef __cpp_lib_span +#ifdef __cpp_lib_concepts +namespace std::ranges { +// Officially, these are defined in , but that is a heavy-hitter header. +// OTOH, must specialize these variable templates, too, so we assume that +// includes some meaningful subset of and just go ahead and use them: +template +constexpr inline bool enable_borrowed_range> = true; +template +constexpr inline bool enable_view> = true; +} // namespace std::ranges +#endif // __cpp_lib_concepts +#endif // __cpp_lib_span +QT_END_INCLUDE_NAMESPACE + namespace QSpanPrivate { template class QSpanBase; @@ -50,6 +66,15 @@ struct is_qspan_helper> : std::true_type {}; template using is_qspan = is_qspan_helper>; +template +struct is_std_span_helper : std::false_type {}; +#ifdef __cpp_lib_span +template +struct is_std_span_helper> : std::true_type {}; +#endif // __cpp_lib_span +template +using is_std_span = is_std_span_helper>; + template struct is_std_array_helper : std::false_type {}; template @@ -107,6 +132,7 @@ protected: using is_compatible_range = std::conjunction< // ### this needs more work, esp. extension to C++20 contiguous iterators std::negation>, + std::negation>, std::negation>, std::negation>>, is_compatible_range_helper @@ -197,6 +223,17 @@ public: : QSpanBase(other.data(), other.size()) {} +#ifdef __cpp_lib_span + template = true> + Q_IMPLICIT constexpr QSpanBase(std::span other) noexcept + : QSpanBase(other.data(), other.size()) + {} + + template = true> + Q_IMPLICIT constexpr QSpanBase(std::span other) + : QSpanBase(other.data(), other.size()) + {} +#endif // __cpp_lib_span }; // class QSpanBase (fixed extent) template @@ -247,6 +284,13 @@ public: Q_IMPLICIT constexpr QSpanBase(QSpan other) noexcept : QSpanBase(other.data(), other.size()) {} + +#if __cpp_lib_span + template = true> + Q_IMPLICIT constexpr QSpanBase(std::span other) noexcept + : QSpanBase(other.data(), other.size()) + {} +#endif // __cpp_lib_span }; // class QSpanBase (dynamic extent) } // namespace QSpanPrivate diff --git a/tests/auto/corelib/tools/qspan/tst_qspan.cpp b/tests/auto/corelib/tools/qspan/tst_qspan.cpp index 9eb3e611633..35539a7f425 100644 --- a/tests/auto/corelib/tools/qspan/tst_qspan.cpp +++ b/tests/auto/corelib/tools/qspan/tst_qspan.cpp @@ -8,6 +8,9 @@ #include #include +#ifdef __cpp_lib_span +#include +#endif #include namespace { @@ -49,6 +52,17 @@ static_assert(std::is_trivially_destructible_v>); static_assert(std::is_convertible_v, QSpan>); static_assert(std::is_convertible_v, QSpan>); +#ifdef __cpp_lib_span +static_assert(std::is_convertible_v, QSpan>); +static_assert(std::is_convertible_v, QSpan>); + +#ifdef __cpp_lib_concepts +// requires enable_borrowed_range +static_assert(std::is_convertible_v, std::span>); +static_assert(std::is_convertible_v, std::span>); +#endif // __cpp_lib_concepts +#endif // __cpp_lib_span + // // Mutable spans implicitly convert to read-only ones, but not vice versa: // @@ -60,6 +74,28 @@ static_assert(!std::is_convertible_v, QSpan>); static_assert(!std::is_convertible_v, QSpan>); static_assert(!std::is_convertible_v, QSpan>); +#ifdef __cpp_lib_span +static_assert(std::is_convertible_v, QSpan>); +static_assert(std::is_convertible_v, QSpan>); +static_assert(std::is_convertible_v, QSpan>); + +static_assert(!std::is_convertible_v, QSpan>); +static_assert(!std::is_convertible_v, QSpan>); +static_assert(!std::is_convertible_v, QSpan>); + +static_assert(std::is_convertible_v, std::span>); +// fixed-size std::span constructors are explicit: +static_assert(!std::is_convertible_v, std::span>); +static_assert(!std::is_convertible_v, std::span>); +// observe: is_convertible, but is_constuctible! +static_assert(std::is_constructible_v, QSpan>); +static_assert(std::is_constructible_v, QSpan>); + +static_assert(!std::is_convertible_v, std::span>); +static_assert(!std::is_convertible_v, std::span>); +static_assert(!std::is_convertible_v, std::span>); +#endif // __cpp_lib_span + class tst_QSpan : public QObject { Q_OBJECT