diff --git a/src/corelib/tools/qspan.h b/src/corelib/tools/qspan.h index e8aa8f3254f..c9de1005a77 100644 --- a/src/corelib/tools/qspan.h +++ b/src/corelib/tools/qspan.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #ifdef __cpp_lib_span @@ -224,6 +225,11 @@ public: : QSpanBase(other.data(), other.size()) {} + template , bool> = true> + Q_IMPLICIT constexpr QSpanBase(std::initializer_list> il) + : QSpanBase(il.begin(), il.size()) + {} + #ifdef __cpp_lib_span template = true> Q_IMPLICIT constexpr QSpanBase(std::span other) noexcept @@ -286,6 +292,11 @@ public: : QSpanBase(other.data(), other.size()) {} + template , bool> = true> + Q_IMPLICIT constexpr QSpanBase(std::initializer_list> il) noexcept + : QSpanBase(il.begin(), il.size()) + {} + #if __cpp_lib_span template = true> Q_IMPLICIT constexpr QSpanBase(std::span other) noexcept @@ -347,6 +358,7 @@ public: template = true> constexpr QSpan(Range &&r); template = true> constexpr QSpan(QSpan other) noexcept; template = true> constexpr QSpan(std::span other) noexcept; + constexpr QSpan(std::initializer_list il); #endif // Q_QDOC // [span.obs] diff --git a/src/corelib/tools/qspan.qdoc b/src/corelib/tools/qspan.qdoc index 474d5e8debf..472f122877d 100644 --- a/src/corelib/tools/qspan.qdoc +++ b/src/corelib/tools/qspan.qdoc @@ -341,6 +341,18 @@ \endlist */ +/*! + \fn template QSpan::QSpan(std::initializer_list il); + + Constructs a QSpan referencing the data in the supplied initializer list \a il. + + \note This constructor participates in overload resolution only if \c{T} is \c{const}-qualified. + + \note This constructor is \c{noexcept} only if \c{E} is \c{std::dynamic_extent}. + + \note If \c{E} is not \c{std::dynamic_extent} and the size of \a il is not \c{E}, the behavior is undefined. +*/ + // // Member functions: sizes // diff --git a/tests/auto/corelib/tools/qspan/tst_qspan.cpp b/tests/auto/corelib/tools/qspan/tst_qspan.cpp index 52f5d6362af..91d2ecf739a 100644 --- a/tests/auto/corelib/tools/qspan/tst_qspan.cpp +++ b/tests/auto/corelib/tools/qspan/tst_qspan.cpp @@ -99,6 +99,15 @@ static_assert(!std::is_convertible_v, std::span>); // Spans don't convert from nonsense: static_assert(!std::is_constructible_v, int&&>); +// Span is constructible from initializer_list +static_assert( std::is_convertible_v, QSpan>); +static_assert(!std::is_convertible_v, QSpan< int>>); +static_assert(!std::is_constructible_v, std::initializer_list>); + +static_assert( std::is_convertible_v, QSpan>); // non-standard, but QSpan considers initializer_list a range +static_assert( std::is_constructible_v, std::initializer_list>); +static_assert(!std::is_constructible_v, std::initializer_list>); + class tst_QSpan : public QObject { Q_OBJECT @@ -114,6 +123,7 @@ private Q_SLOTS: void fromZeroSizeStdArray() const; void fromStdVector() const; void fromQList() const; + void fromInitList() const; private: template @@ -322,9 +332,11 @@ void tst_QSpan::from_container_impl(C &&c) const { const auto c_size = qsizetype(QSpanPrivate::adl_size(c)); const auto c_data = QSpanPrivate::adl_data(c); + + using V = std::remove_reference_t>; { QSpan si = c; // CTAD - static_assert(std::is_same_v>); + static_assert(std::is_same_v>); QCOMPARE_EQ(si.size(), c_size); QCOMPARE_EQ(si.data(), c_data); @@ -421,6 +433,17 @@ void tst_QSpan::fromQList() const from_variable_size_container_impl(li); } +void tst_QSpan::fromInitList() const +{ + from_variable_size_container_impl(std::initializer_list{42, 84, 168, 336}); + + auto l1 = [](QSpan){}; + l1({1, 2, 3}); + + auto l2 = [](QSpan){}; + l2({4, 5, 6}); +} + #undef RETURN_IF_FAILED QTEST_APPLESS_MAIN(tst_QSpan);