mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 05:40:09 +00:00
[libc++][span] P2447R4: std::span
over an initializer list (#78157)
Implements: https://wg21.link/P2447R6 - https://eel.is/c++draft/span.syn - https://eel.is/c++draft/span.overview - https://eel.is/c++draft/span.cons - https://eel.is/c++draft/diff --------- Co-authored-by: Zingam <zingam@outlook.com>
This commit is contained in:
parent
552f5549de
commit
dbbeee6b83
@ -438,7 +438,7 @@ Status
|
||||
--------------------------------------------------- -----------------
|
||||
``__cpp_lib_span_at`` ``202311L``
|
||||
--------------------------------------------------- -----------------
|
||||
``__cpp_lib_span_initializer_list`` *unimplemented*
|
||||
``__cpp_lib_span_initializer_list`` ``202311L``
|
||||
--------------------------------------------------- -----------------
|
||||
``__cpp_lib_sstream_from_string_view`` *unimplemented*
|
||||
--------------------------------------------------- -----------------
|
||||
|
@ -61,6 +61,7 @@ Implemented Papers
|
||||
- P1759R6 - Native handles and file streams
|
||||
- P2868R3 - Remove Deprecated ``std::allocator`` Typedef From C++26
|
||||
- P2517R1 - Add a conditional ``noexcept`` specification to ``std::apply``
|
||||
- P2447R6 - ``span`` over initializer list
|
||||
|
||||
|
||||
Improvements and New Features
|
||||
|
@ -34,7 +34,7 @@
|
||||
"`P2918R2 <https://wg21.link/P2918R2>`__","LWG","Runtime format strings II","Kona November 2023","|Complete|","18.0","|format|"
|
||||
"`P2909R4 <https://wg21.link/P2909R4>`__","LWG","Fix formatting of code units as integers (Dude, where’s my ``char``?)","Kona November 2023","|Complete|","18.0","|format| |DR|"
|
||||
"`P0952R2 <https://wg21.link/P0952R2>`__","LWG","A new specification for ``std::generate_canonical``","Kona November 2023","","",""
|
||||
"`P2447R6 <https://wg21.link/P2447R6>`__","LWG","``std::span`` over an initializer list","Kona November 2023","","",""
|
||||
"`P2447R6 <https://wg21.link/P2447R6>`__","LWG","``std::span`` over an initializer list","Kona November 2023","|Complete|","18.0",""
|
||||
"`P2821R5 <https://wg21.link/P2821R5>`__","LWG","``span.at()``","Kona November 2023","|Complete|","18.0",""
|
||||
"`P2868R3 <https://wg21.link/P2868R3>`__","LWG","Remove Deprecated ``std::allocator`` Typedef From C++26","Kona November 2023","|Complete|","18.0",""
|
||||
"`P2870R3 <https://wg21.link/P2870R3>`__","LWG","Remove ``basic_string::reserve()`` From C++26","Kona November 2023","|Complete|","18.0",""
|
||||
|
|
@ -68,6 +68,7 @@ public:
|
||||
constexpr span(const array<value_type, N>& arr) noexcept;
|
||||
template<class R>
|
||||
constexpr explicit(Extent != dynamic_extent) span(R&& r);
|
||||
constexpr explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il); // Since C++26
|
||||
constexpr span(const span& other) noexcept = default;
|
||||
template <class OtherElementType, size_t OtherExtent>
|
||||
constexpr explicit(Extent != dynamic_extent) span(const span<OtherElementType, OtherExtent>& s) noexcept;
|
||||
@ -228,6 +229,15 @@ public:
|
||||
requires(_Sz == 0)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr span() noexcept : __data_{nullptr} {}
|
||||
|
||||
# if _LIBCPP_STD_VER >= 26
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr explicit span(std::initializer_list<value_type> __il)
|
||||
requires is_const_v<element_type>
|
||||
: __data_{__il.begin()} {
|
||||
_LIBCPP_ASSERT_VALID_INPUT_RANGE(
|
||||
_Extent == __il.size(), "Size mismatch in span's constructor _Extent != __il.size().");
|
||||
}
|
||||
# endif
|
||||
|
||||
constexpr span(const span&) noexcept = default;
|
||||
constexpr span& operator=(const span&) noexcept = default;
|
||||
|
||||
@ -397,6 +407,12 @@ public:
|
||||
// [span.cons], span constructors, copy, assignment, and destructor
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr span() noexcept : __data_{nullptr}, __size_{0} {}
|
||||
|
||||
# if _LIBCPP_STD_VER >= 26
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr span(std::initializer_list<value_type> __il)
|
||||
requires is_const_v<element_type>
|
||||
: __data_{__il.begin()}, __size_{__il.size()} {}
|
||||
# endif
|
||||
|
||||
constexpr span(const span&) noexcept = default;
|
||||
constexpr span& operator=(const span&) noexcept = default;
|
||||
|
||||
|
@ -507,7 +507,7 @@ __cpp_lib_within_lifetime 202306L <type_traits>
|
||||
// # define __cpp_lib_saturation_arithmetic 202311L
|
||||
// # define __cpp_lib_smart_ptr_owner_equality 202306L
|
||||
# define __cpp_lib_span_at 202311L
|
||||
// # define __cpp_lib_span_initializer_list 202311L
|
||||
# define __cpp_lib_span_initializer_list 202311L
|
||||
// # define __cpp_lib_sstream_from_string_view 202306L
|
||||
// # define __cpp_lib_submdspan 202306L
|
||||
// # define __cpp_lib_text_encoding 202306L
|
||||
|
@ -94,7 +94,11 @@ constexpr bool testSpan()
|
||||
assert(s4.data() == val && s4.size() == 2);
|
||||
|
||||
std::span<const int> s5 = {{1,2}};
|
||||
#if TEST_STD_VER >= 26
|
||||
std::span<const int, 2> s6({1, 2});
|
||||
#else
|
||||
std::span<const int, 2> s6 = {{1,2}};
|
||||
#endif
|
||||
assert(s5.size() == 2); // and it dangles
|
||||
assert(s6.size() == 2); // and it dangles
|
||||
|
||||
|
@ -0,0 +1,32 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
|
||||
|
||||
// REQUIRES: has-unix-headers
|
||||
// REQUIRES: libcpp-hardening-mode={{extensive|debug}}
|
||||
// XFAIL: availability-verbose_abort-missing
|
||||
|
||||
// <span>
|
||||
|
||||
// constexpr explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il); // Since C++26
|
||||
|
||||
#include <cassert>
|
||||
#include <initializer_list>
|
||||
#include <span>
|
||||
|
||||
#include "check_assertion.h"
|
||||
|
||||
int main(int, char**) {
|
||||
TEST_LIBCPP_ASSERT_FAILURE(
|
||||
(std::span<const int, 4>({1, 2, 3, 9084, 5})), "Size mismatch in span's constructor _Extent != __il.size().");
|
||||
TEST_LIBCPP_ASSERT_FAILURE((std::span<const int, 4>(std::initializer_list<int>{1, 2, 3, 9084, 5})),
|
||||
"Size mismatch in span's constructor _Extent != __il.size().");
|
||||
|
||||
return 0;
|
||||
}
|
@ -5,39 +5,134 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
|
||||
// <span>
|
||||
|
||||
#include <span>
|
||||
// constexpr explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il); // Since C++26
|
||||
|
||||
#include <any>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <initializer_list>
|
||||
#include <span>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_convertible.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
#if TEST_STD_VER >= 26
|
||||
|
||||
// SFINAE
|
||||
|
||||
template <typename T>
|
||||
concept ConstElementType = std::is_const_v<typename T::element_type>;
|
||||
|
||||
static_assert(ConstElementType<std::span<const int>>);
|
||||
static_assert(!ConstElementType<std::span<int>>);
|
||||
static_assert(ConstElementType<std::span<const int, 94>>);
|
||||
static_assert(!ConstElementType<std::span<int, 94>>);
|
||||
|
||||
// Constructor constraings
|
||||
|
||||
template <typename I, typename T, std::size_t... N>
|
||||
concept HasInitializerListCtr = requires(I il) { std::span<T, N...>{il}; };
|
||||
|
||||
static_assert(HasInitializerListCtr<std::initializer_list<const int>, const int>);
|
||||
static_assert(!HasInitializerListCtr<std::initializer_list<int>, int>);
|
||||
static_assert(HasInitializerListCtr<std::initializer_list<const int>, const int, 94>);
|
||||
static_assert(!HasInitializerListCtr<std::initializer_list<int>, int, 94>);
|
||||
|
||||
// Constructor conditionally explicit
|
||||
|
||||
static_assert(!test_convertible<std::span<const int, 28>, std::initializer_list<int>>(),
|
||||
"This constructor must be explicit");
|
||||
static_assert(std::is_constructible_v<std::span<const int, 28>, std::initializer_list<int>>);
|
||||
static_assert(test_convertible<std::span<const int>, std::initializer_list<int>>(),
|
||||
"This constructor must not be explicit");
|
||||
static_assert(std::is_constructible_v<std::span<const int>, std::initializer_list<int>>);
|
||||
|
||||
#endif
|
||||
|
||||
struct Sink {
|
||||
constexpr Sink() = default;
|
||||
constexpr Sink(Sink*) {}
|
||||
constexpr Sink() = default;
|
||||
constexpr Sink(Sink*) {}
|
||||
};
|
||||
|
||||
constexpr std::size_t count(std::span<const Sink> sp) {
|
||||
return sp.size();
|
||||
}
|
||||
constexpr std::size_t count(std::span<const Sink> sp) { return sp.size(); }
|
||||
|
||||
template<int N>
|
||||
constexpr std::size_t countn(std::span<const Sink, N> sp) {
|
||||
return sp.size();
|
||||
template <std::size_t N>
|
||||
constexpr std::size_t count_n(std::span<const Sink, N> sp) {
|
||||
return sp.size();
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
#if TEST_STD_VER >= 26
|
||||
// Dynamic extent
|
||||
{
|
||||
Sink a[10];
|
||||
|
||||
assert(count({a}) == 1);
|
||||
assert(count({a, a + 10}) == 2);
|
||||
assert(count({a, a + 1, a + 2}) == 3);
|
||||
assert(count(std::initializer_list<Sink>{a[0], a[1], a[2], a[3]}) == 4);
|
||||
}
|
||||
#else
|
||||
{
|
||||
Sink a[10];
|
||||
|
||||
assert(count({a}) == 10);
|
||||
assert(count({a, a+10}) == 10);
|
||||
assert(countn<10>({a}) == 10);
|
||||
return true;
|
||||
assert(count({a, a + 10}) == 10);
|
||||
assert(count_n<10>({a}) == 10);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test P2447R4 "Annex C examples"
|
||||
|
||||
constexpr int three(std::span<void* const> sp) { return sp.size(); }
|
||||
|
||||
constexpr int four(std::span<const std::any> sp) { return sp.size(); }
|
||||
|
||||
bool test_P2447R4_annex_c_examples() {
|
||||
// 1. Overload resolution is affected
|
||||
// --> tested in "initializer_list.verify.cpp"
|
||||
|
||||
// 2. The `initializer_list` ctor has high precedence
|
||||
// --> tested in "initializer_list.verify.cpp"
|
||||
|
||||
// 3. Implicit two-argument construction with a highly convertible value_type
|
||||
#if TEST_STD_VER >= 26
|
||||
{
|
||||
void* a[10];
|
||||
assert(three({a, 0}) == 2);
|
||||
}
|
||||
{
|
||||
std::any a[10];
|
||||
assert(four({a, a + 10}) == 2);
|
||||
}
|
||||
#else
|
||||
{
|
||||
void* a[10];
|
||||
assert(three({a, 0}) == 0);
|
||||
}
|
||||
{
|
||||
std::any a[10];
|
||||
assert(four({a, a + 10}) == 10);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
assert(test());
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
assert(test_P2447R4_annex_c_examples());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,48 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
|
||||
// <span>
|
||||
|
||||
// constexpr explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il); // Since C++26
|
||||
|
||||
#include <span>
|
||||
#include <utility>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
// Test P2447R4 "Annex C examples"
|
||||
|
||||
void one(std::pair<int, int>);
|
||||
void one(std::span<const int>);
|
||||
|
||||
void two(std::span<const int, 2>);
|
||||
|
||||
void test_P2447R4_annex_c_examples() {
|
||||
// 1. Overload resolution is affected
|
||||
#if TEST_STD_VER >= 26
|
||||
// expected-error@+1 {{call to 'one' is ambiguous}}
|
||||
one({1, 2});
|
||||
#else
|
||||
// expected-no-diagnostics
|
||||
one({1, 2});
|
||||
#endif
|
||||
|
||||
// 2. The `initializer_list` ctor has high precedence
|
||||
#if TEST_STD_VER >= 26
|
||||
// expected-error@+1 {{chosen constructor is explicit in copy-initialization}}
|
||||
two({{1, 2}});
|
||||
#else
|
||||
// expected-no-diagnostics
|
||||
two({{1, 2}});
|
||||
#endif
|
||||
|
||||
// 3. Implicit two-argument construction with a highly convertible value_type
|
||||
// --> tested in "initializer_list.pass.cpp"
|
||||
}
|
@ -13,22 +13,31 @@
|
||||
// constexpr explicit(Extent != dynamic_extent) span(It first, size_type count);
|
||||
// If Extent is not equal to dynamic_extent, then count shall be equal to Extent.
|
||||
//
|
||||
// constexpr explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il); // Since C++26
|
||||
|
||||
#include <span>
|
||||
#include <cstddef>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
template <class T, std::size_t extent>
|
||||
std::span<T, extent> createImplicitSpan(T* ptr, std::size_t len) {
|
||||
return {ptr, len}; // expected-error {{chosen constructor is explicit in copy-initialization}}
|
||||
}
|
||||
|
||||
void f() {
|
||||
void test() {
|
||||
// explicit constructor necessary
|
||||
int arr[] = {1, 2, 3};
|
||||
createImplicitSpan<int, 1>(arr, 3);
|
||||
|
||||
std::span<int> sp = {0, 0}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
|
||||
std::span<int, 2> sp2 = {0, 0}; // expected-error {{no matching constructor for initialization of 'std::span<int, 2>'}}
|
||||
std::span<const int> csp = {0, 0}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
|
||||
std::span<const int, 2> csp2 = {0, 0}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 2>'}}
|
||||
// expected-error@+1 {{no matching constructor for initialization of 'std::span<int>'}}
|
||||
std::span<int> sp = {0, 0};
|
||||
// expected-error@+1 {{no matching constructor for initialization of 'std::span<int, 2>'}}
|
||||
std::span<int, 2> sp2 = {0, 0};
|
||||
#if TEST_STD_VER < 26
|
||||
// expected-error@+1 {{no matching constructor for initialization of 'std::span<const int>'}}
|
||||
std::span<const int> csp = {0, 0};
|
||||
// expected-error@+1 {{no matching constructor for initialization of 'std::span<const int, 2>'}}
|
||||
std::span<const int, 2> csp2 = {0, 0};
|
||||
#endif
|
||||
}
|
||||
|
@ -116,17 +116,11 @@
|
||||
# error "__cpp_lib_span_at should have the value 202311L in c++26"
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_VERSION)
|
||||
# ifndef __cpp_lib_span_initializer_list
|
||||
# error "__cpp_lib_span_initializer_list should be defined in c++26"
|
||||
# endif
|
||||
# if __cpp_lib_span_initializer_list != 202311L
|
||||
# error "__cpp_lib_span_initializer_list should have the value 202311L in c++26"
|
||||
# endif
|
||||
# else // _LIBCPP_VERSION
|
||||
# ifdef __cpp_lib_span_initializer_list
|
||||
# error "__cpp_lib_span_initializer_list should not be defined because it is unimplemented in libc++!"
|
||||
# endif
|
||||
# ifndef __cpp_lib_span_initializer_list
|
||||
# error "__cpp_lib_span_initializer_list should be defined in c++26"
|
||||
# endif
|
||||
# if __cpp_lib_span_initializer_list != 202311L
|
||||
# error "__cpp_lib_span_initializer_list should have the value 202311L in c++26"
|
||||
# endif
|
||||
|
||||
#endif // TEST_STD_VER > 23
|
||||
|
@ -7294,17 +7294,11 @@
|
||||
# error "__cpp_lib_span_at should have the value 202311L in c++26"
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_VERSION)
|
||||
# ifndef __cpp_lib_span_initializer_list
|
||||
# error "__cpp_lib_span_initializer_list should be defined in c++26"
|
||||
# endif
|
||||
# if __cpp_lib_span_initializer_list != 202311L
|
||||
# error "__cpp_lib_span_initializer_list should have the value 202311L in c++26"
|
||||
# endif
|
||||
# else // _LIBCPP_VERSION
|
||||
# ifdef __cpp_lib_span_initializer_list
|
||||
# error "__cpp_lib_span_initializer_list should not be defined because it is unimplemented in libc++!"
|
||||
# endif
|
||||
# ifndef __cpp_lib_span_initializer_list
|
||||
# error "__cpp_lib_span_initializer_list should be defined in c++26"
|
||||
# endif
|
||||
# if __cpp_lib_span_initializer_list != 202311L
|
||||
# error "__cpp_lib_span_initializer_list should have the value 202311L in c++26"
|
||||
# endif
|
||||
|
||||
# if !defined(_LIBCPP_VERSION)
|
||||
|
@ -1093,7 +1093,6 @@ feature_test_macros = [
|
||||
"name": "__cpp_lib_span_initializer_list",
|
||||
"values": {"c++26": 202311}, # P2447R6 std::span over an initializer list
|
||||
"headers": ["span"],
|
||||
"unimplemented": True,
|
||||
},
|
||||
{
|
||||
"name": "__cpp_lib_spanstream",
|
||||
|
Loading…
Reference in New Issue
Block a user