mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-16 05:01:56 +00:00
[libcxx][span] Implement P1976R2
This resolves the NB comment about the construction of a fixed-size span from a dynamic range. Differential Revision: https://reviews.llvm.org/D74577
This commit is contained in:
parent
2668775f66
commit
6d2599e4f7
@ -198,6 +198,8 @@ Status
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_ranges`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_span`` ``202002L``
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_three_way_comparison`` *unimplemented*
|
||||
------------------------------------------------- -----------------
|
||||
``__cpp_lib_to_array`` ``201907L``
|
||||
|
@ -53,8 +53,8 @@ public:
|
||||
|
||||
// [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>
|
||||
@ -62,12 +62,12 @@ public:
|
||||
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;
|
||||
|
||||
@ -214,15 +214,31 @@ public:
|
||||
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,
|
||||
@ -233,7 +249,7 @@ public:
|
||||
|
||||
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
|
||||
@ -247,7 +263,7 @@ public:
|
||||
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>
|
||||
@ -255,7 +271,7 @@ public:
|
||||
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
|
||||
@ -279,7 +295,9 @@ public:
|
||||
{
|
||||
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};
|
||||
}
|
||||
|
||||
|
||||
@ -337,10 +355,10 @@ public:
|
||||
}
|
||||
|
||||
_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;
|
||||
@ -418,7 +436,7 @@ public:
|
||||
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>
|
||||
@ -426,7 +444,7 @@ public:
|
||||
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
|
||||
@ -449,7 +467,7 @@ public:
|
||||
{
|
||||
_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>
|
||||
|
@ -98,6 +98,7 @@ __cpp_lib_shared_mutex 201505L <shared_mutex>
|
||||
__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>
|
||||
@ -234,8 +235,9 @@ __cpp_lib_void_t 201411L <type_traits>
|
||||
# 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
|
||||
|
@ -185,13 +185,14 @@ int main(int, char**)
|
||||
|
||||
// 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, "" );
|
||||
@ -247,10 +248,11 @@ int main(int, char**)
|
||||
|
||||
// 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)
|
||||
@ -279,10 +281,11 @@ int main(int, char**)
|
||||
}
|
||||
|
||||
{
|
||||
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)
|
||||
|
@ -63,6 +63,10 @@ private:
|
||||
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**)
|
||||
{
|
||||
@ -106,12 +110,14 @@ 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;
|
||||
}
|
||||
|
@ -84,14 +84,32 @@ constexpr bool testConstexprSpan()
|
||||
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);
|
||||
}
|
||||
@ -105,12 +123,23 @@ int main(int, char**)
|
||||
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;
|
||||
|
@ -27,6 +27,11 @@ const int carr[] = {4,5,6};
|
||||
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
|
||||
@ -60,5 +65,10 @@ int main(int, char**)
|
||||
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;
|
||||
}
|
||||
|
@ -27,6 +27,11 @@ const int carr[] = {4,5,6};
|
||||
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
|
||||
@ -60,5 +65,10 @@ int main(int, char**)
|
||||
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;
|
||||
}
|
||||
|
@ -24,6 +24,11 @@
|
||||
|
||||
#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;
|
||||
@ -101,5 +106,10 @@ int main(int, char**)
|
||||
|
||||
checkCV();
|
||||
|
||||
// explicit constructor necessary
|
||||
{
|
||||
createImplicitSpan<int, 1>(sp);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,52 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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; }
|
@ -85,6 +85,7 @@
|
||||
__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]
|
||||
@ -391,6 +392,10 @@
|
||||
# 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
|
||||
@ -784,6 +789,10 @@
|
||||
# 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
|
||||
@ -1381,6 +1390,10 @@
|
||||
# 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
|
||||
@ -2116,6 +2129,13 @@
|
||||
# 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
|
||||
|
@ -591,6 +591,12 @@ feature_test_macros = sorted([ add_version_header(x) for x in [
|
||||
},
|
||||
"headers": ["array"],
|
||||
},
|
||||
{"name": "__cpp_lib_span",
|
||||
"values": {
|
||||
"c++2a": int(202002),
|
||||
},
|
||||
"headers": ["span"],
|
||||
},
|
||||
]], key=lambda tc: tc["name"])
|
||||
|
||||
def get_std_dialects():
|
||||
|
Loading…
x
Reference in New Issue
Block a user