------------------------------------------------- -----------------
``__cpp_lib_ranges`` *unimplemented*
------------------------------------------------- -----------------
+ ``__cpp_lib_span`` ``202002L``
+ ------------------------------------------------- -----------------
``__cpp_lib_three_way_comparison`` *unimplemented*
------------------------------------------------- -----------------
``__cpp_lib_to_array`` ``201907L``
// [span.cons], span constructors, copy, assignment, and destructor
constexpr span() noexcept;
- constexpr span(pointer ptr, size_type count);
- constexpr span(pointer firstElem, pointer lastElem);
+ constexpr explicit(Extent != dynamic_extent) span(pointer ptr, size_type count);
+ constexpr explicit(Extent != dynamic_extent) span(pointer firstElem, pointer lastElem);
template <size_t N>
constexpr span(element_type (&arr)[N]) noexcept;
template <size_t N>
template <size_t N>
constexpr span(const array<value_type, N>& arr) noexcept;
template <class Container>
- constexpr span(Container& cont);
+ constexpr explicit(Extent != dynamic_extent) span(Container& cont);
template <class Container>
- constexpr span(const Container& cont);
+ constexpr explicit(Extent != dynamic_extent) span(const Container& cont);
constexpr span(const span& other) noexcept = default;
template <class OtherElementType, size_t OtherExtent>
- constexpr span(const span<OtherElementType, OtherExtent>& s) noexcept;
+ constexpr explicit(Extent != dynamic_extent) span(const span<OtherElementType, OtherExtent>& s) noexcept;
~span() noexcept = default;
constexpr span& operator=(const span& other) noexcept = default;
constexpr span (const span&) noexcept = default;
constexpr span& operator=(const span&) noexcept = default;
- _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, size_type __count) : __data{__ptr}
+ _LIBCPP_INLINE_VISIBILITY constexpr explicit span(pointer __ptr, size_type __count) : __data{__ptr}
{ (void)__count; _LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (ptr, len)"); }
- _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}
+ _LIBCPP_INLINE_VISIBILITY constexpr explicit span(pointer __f, pointer __l) : __data{__f}
{ (void)__l; _LIBCPP_ASSERT(_Extent == distance(__f, __l), "size mismatch in span's constructor (ptr, ptr)"); }
_LIBCPP_INLINE_VISIBILITY constexpr span(element_type (&__arr)[_Extent]) noexcept : __data{__arr} {}
_LIBCPP_INLINE_VISIBILITY constexpr span( array<value_type, _Extent>& __arr) noexcept : __data{__arr.data()} {}
_LIBCPP_INLINE_VISIBILITY constexpr span(const array<value_type, _Extent>& __arr) noexcept : __data{__arr.data()} {}
+ template <class _Container>
+ _LIBCPP_INLINE_VISIBILITY
+ constexpr explicit span( _Container& __c,
+ enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr)
+ : __data{_VSTD::data(__c)} {
+ _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (range)");
+ }
+
+ template <class _Container>
+ _LIBCPP_INLINE_VISIBILITY
+ constexpr explicit span(const _Container& __c,
+ enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr)
+ : __data{_VSTD::data(__c)} {
+ _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (range)");
+ }
+
template <class _OtherElementType>
_LIBCPP_INLINE_VISIBILITY
constexpr span(const span<_OtherElementType, _Extent>& __other,
template <class _OtherElementType>
_LIBCPP_INLINE_VISIBILITY
- constexpr span(const span<_OtherElementType, dynamic_extent>& __other,
+ constexpr explicit span(const span<_OtherElementType, dynamic_extent>& __other,
enable_if_t<
is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
nullptr_t> = nullptr) noexcept
constexpr span<element_type, _Count> first() const noexcept
{
static_assert(_Count <= _Extent, "Count out of range in span::first()");
- return {data(), _Count};
+ return span<element_type, _Count>{data(), _Count};
}
template <size_t _Count>
constexpr span<element_type, _Count> last() const noexcept
{
static_assert(_Count <= _Extent, "Count out of range in span::last()");
- return {data() + size() - _Count, _Count};
+ return span<element_type, _Count>{data() + size() - _Count, _Count};
}
_LIBCPP_INLINE_VISIBILITY
{
static_assert(_Offset <= _Extent, "Offset out of range in span::subspan()");
static_assert(_Count == dynamic_extent || _Count <= _Extent - _Offset, "Offset + count out of range in span::subspan()");
- return {data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
+
+ using _ReturnType = span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset>;
+ return _ReturnType{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
}
}
_LIBCPP_INLINE_VISIBILITY span<const byte, _Extent * sizeof(element_type)> __as_bytes() const noexcept
- { return {reinterpret_cast<const byte *>(data()), size_bytes()}; }
+ { return span<const byte, _Extent * sizeof(element_type)>{reinterpret_cast<const byte *>(data()), size_bytes()}; }
_LIBCPP_INLINE_VISIBILITY span<byte, _Extent * sizeof(element_type)> __as_writable_bytes() const noexcept
- { return {reinterpret_cast<byte *>(data()), size_bytes()}; }
+ { return span<byte, _Extent * sizeof(element_type)>{reinterpret_cast<byte *>(data()), size_bytes()}; }
private:
pointer __data;
constexpr span<element_type, _Count> first() const noexcept
{
_LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::first()");
- return {data(), _Count};
+ return span<element_type, _Count>{data(), _Count};
}
template <size_t _Count>
constexpr span<element_type, _Count> last() const noexcept
{
_LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::last()");
- return {data() + size() - _Count, _Count};
+ return span<element_type, _Count>{data() + size() - _Count, _Count};
}
_LIBCPP_INLINE_VISIBILITY
{
_LIBCPP_ASSERT(_Offset <= size(), "Offset out of range in span::subspan()");
_LIBCPP_ASSERT(_Count == dynamic_extent || _Count <= size() - _Offset, "Offset + count out of range in span::subspan()");
- return {data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
+ return span<element_type, _Count>{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
}
constexpr span<element_type, dynamic_extent>
__cpp_lib_shared_ptr_arrays 201611L <memory>
__cpp_lib_shared_ptr_weak_type 201606L <memory>
__cpp_lib_shared_timed_mutex 201402L <shared_mutex>
+__cpp_lib_span 202002L <span>
__cpp_lib_string_udls 201304L <string>
__cpp_lib_string_view 201606L <string> <string_view>
__cpp_lib_three_way_comparison 201711L <compare>
# endif
# define __cpp_lib_list_remove_return_type 201806L
// # define __cpp_lib_ranges 201811L
-# define __cpp_lib_to_array 201907L
+# define __cpp_lib_span 202002L
// # define __cpp_lib_three_way_comparison 201711L
+# define __cpp_lib_to_array 201907L
#endif
#endif // _LIBCPP_VERSIONH
// constexpr statically sized assignment
{
- constexpr std::span<const int,2> spans[] = {
- {carr1, 2},
- {carr1 + 1, 2},
- {carr1 + 2, 2},
- {carr2, 2},
- {carr2 + 1, 2},
- {carr3, 2}
+ using spanType = std::span<const int,2>;
+ constexpr spanType spans[] = {
+ spanType{carr1, 2},
+ spanType{carr1 + 1, 2},
+ spanType{carr1 + 2, 2},
+ spanType{carr2, 2},
+ spanType{carr2 + 1, 2},
+ spanType{carr3, 2}
};
static_assert(std::size(spans) == 6, "" );
// statically sized assignment
{
- std::span<int,2> spans[] = {
- {arr, arr + 2},
- {arr + 1, arr + 3},
- {arr + 2, arr + 4}
+ using spanType = std::span<int,2>;
+ spanType spans[] = {
+ spanType{arr, arr + 2},
+ spanType{arr + 1, arr + 3},
+ spanType{arr + 2, arr + 4}
};
for (size_t i = 0; i < std::size(spans); ++i)
}
{
- std::span<std::string, 1> spans[] = {
- {strs, strs + 1},
- {strs + 1, strs + 2},
- {strs + 2, strs + 3}
+ using spanType = std::span<std::string, 1>;
+ spanType spans[] = {
+ spanType{strs, strs + 1},
+ spanType{strs + 1, strs + 2},
+ spanType{strs + 2, strs + 3}
};
for (size_t i = 0; i < std::size(spans); ++i)
const T *data() const {return nullptr;}
};
+template<class T, size_t extent, class container>
+std::span<T, extent> createImplicitSpan(container c) {
+ return {c}; // expected-error {{chosen constructor is explicit in copy-initialization}}
+}
int main(int, char**)
{
std::span< volatile int> s7{cv}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
}
-// statically sized
+// explicit constructor necessary
{
- IsAContainer<int> c;
- std::span<int,1> s1{c}; // expected-error {{no matching constructor for initialization of 'std::span<int, 1>'}}
- }
+ IsAContainer<int> c;
+ const IsAContainer<int> cc;
+ createImplicitSpan<int, 1>(c);
+ createImplicitSpan<int, 1>(cc);
+ }
return 0;
}
return s1.data() == val.getV() && s1.size() == 1;
}
+template <typename T>
+constexpr bool testConstexprSpanStatic()
+{
+ constexpr IsAContainer<const T> val{};
+ std::span<const T, 1> s1{val};
+ return s1.data() == val.getV() && s1.size() == 1;
+}
template <typename T>
void testRuntimeSpan()
{
IsAContainer<T> val{};
const IsAContainer<T> cVal;
- std::span<T> s1{val};
- std::span<const T> s2{cVal};
+ std::span<T> s1{val};
+ std::span<const T> s2{cVal};
+ assert(s1.data() == val.getV() && s1.size() == 1);
+ assert(s2.data() == cVal.getV() && s2.size() == 1);
+}
+
+template <typename T>
+void testRuntimeSpanStatic()
+{
+ IsAContainer<T> val{};
+ const IsAContainer<T> cVal;
+ std::span<T, 1> s1{val};
+ std::span<const T, 1> s2{cVal};
assert(s1.data() == val.getV() && s1.size() == 1);
assert(s2.data() == cVal.getV() && s2.size() == 1);
}
static_assert(testConstexprSpan<double>(), "");
static_assert(testConstexprSpan<A>(), "");
+ static_assert(testConstexprSpanStatic<int>(), "");
+ static_assert(testConstexprSpanStatic<long>(), "");
+ static_assert(testConstexprSpanStatic<double>(), "");
+ static_assert(testConstexprSpanStatic<A>(), "");
+
testRuntimeSpan<int>();
testRuntimeSpan<long>();
testRuntimeSpan<double>();
testRuntimeSpan<std::string>();
testRuntimeSpan<A>();
+ testRuntimeSpanStatic<int>();
+ testRuntimeSpanStatic<long>();
+ testRuntimeSpanStatic<double>();
+ testRuntimeSpanStatic<std::string>();
+ testRuntimeSpanStatic<A>();
+
checkCV();
return 0;
volatile int varr[] = {7,8,9};
const volatile int cvarr[] = {1,3,5};
+template<class T, size_t extent>
+std::span<T, extent> createImplicitSpan(T* ptr, size_t len) {
+ return {ptr, len}; // expected-error {{chosen constructor is explicit in copy-initialization}}
+}
+
int main(int, char**)
{
// We can't check that the size doesn't match - because that's a runtime property
std::span< volatile int,3> s7{cvarr, 3}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 3>'}}
}
+// explicit constructor necessary
+ {
+ createImplicitSpan<int, 1>(arr, 1);
+ }
+
return 0;
}
volatile int varr[] = {7,8,9};
const volatile int cvarr[] = {1,3,5};
+template<class T, size_t extent>
+std::span<T, extent> createImplicitSpan(T* first, T* last) {
+ return {first, last}; // expected-error {{chosen constructor is explicit in copy-initialization}}
+}
+
int main(int, char**)
{
// We can't check that the size doesn't match - because that's a runtime property
std::span< volatile int,3> s7{cvarr, cvarr + 3}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 3>'}}
}
+ // explicit constructor necessary
+ {
+ createImplicitSpan<int, 1>(arr, arr + 1);
+ }
+
return 0;
}
#include "test_macros.h"
+template<class T, size_t extent, size_t otherExtent>
+std::span<T, extent> createImplicitSpan(std::span<T, otherExtent> s) {
+ return {s}; // expected-error {{chosen constructor is explicit in copy-initialization}}
+}
+
void checkCV ()
{
// std::span< int> sp;
checkCV();
+ // explicit constructor necessary
+ {
+ createImplicitSpan<int, 1>(sp);
+ }
+
return 0;
}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// WARNING: This test was generated by generate_feature_test_macro_components.py
+// and should not be edited manually.
+
+// <span>
+
+// Test the feature test macros defined by <span>
+
+/* Constant Value
+ __cpp_lib_span 202002L [C++2a]
+*/
+
+#include <span>
+#include "test_macros.h"
+
+#if TEST_STD_VER < 14
+
+# ifdef __cpp_lib_span
+# error "__cpp_lib_span should not be defined before c++2a"
+# endif
+
+#elif TEST_STD_VER == 14
+
+# ifdef __cpp_lib_span
+# error "__cpp_lib_span should not be defined before c++2a"
+# endif
+
+#elif TEST_STD_VER == 17
+
+# ifdef __cpp_lib_span
+# error "__cpp_lib_span should not be defined before c++2a"
+# endif
+
+#elif TEST_STD_VER > 17
+
+# ifndef __cpp_lib_span
+# error "__cpp_lib_span should be defined in c++2a"
+# endif
+# if __cpp_lib_span != 202002L
+# error "__cpp_lib_span should have the value 202002L in c++2a"
+# endif
+
+#endif // TEST_STD_VER > 17
+
+int main(int, char**) { return 0; }
__cpp_lib_shared_ptr_arrays 201611L [C++17]
__cpp_lib_shared_ptr_weak_type 201606L [C++17]
__cpp_lib_shared_timed_mutex 201402L [C++14]
+ __cpp_lib_span 202002L [C++2a]
__cpp_lib_string_udls 201304L [C++14]
__cpp_lib_string_view 201606L [C++17]
__cpp_lib_three_way_comparison 201711L [C++2a]
# error "__cpp_lib_shared_timed_mutex should not be defined before c++14"
# endif
+# ifdef __cpp_lib_span
+# error "__cpp_lib_span should not be defined before c++2a"
+# endif
+
# ifdef __cpp_lib_string_udls
# error "__cpp_lib_string_udls should not be defined before c++14"
# endif
# endif
# endif
+# ifdef __cpp_lib_span
+# error "__cpp_lib_span should not be defined before c++2a"
+# endif
+
# ifndef __cpp_lib_string_udls
# error "__cpp_lib_string_udls should be defined in c++14"
# endif
# endif
# endif
+# ifdef __cpp_lib_span
+# error "__cpp_lib_span should not be defined before c++2a"
+# endif
+
# ifndef __cpp_lib_string_udls
# error "__cpp_lib_string_udls should be defined in c++17"
# endif
# endif
# endif
+# ifndef __cpp_lib_span
+# error "__cpp_lib_span should be defined in c++2a"
+# endif
+# if __cpp_lib_span != 202002L
+# error "__cpp_lib_span should have the value 202002L in c++2a"
+# endif
+
# ifndef __cpp_lib_string_udls
# error "__cpp_lib_string_udls should be defined in c++2a"
# endif
},
"headers": ["array"],
},
+ {"name": "__cpp_lib_span",
+ "values": {
+ "c++2a": int(202002),
+ },
+ "headers": ["span"],
+ },
]], key=lambda tc: tc["name"])
def get_std_dialects():