mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-17 08:21:13 +00:00
[libc++][mdspan] Implement default_accessor
This commit implements default_accessor in support of C++23 mdspan (https://wg21.link/p0009). default_accessor is the trivial accessor using plain pointers and reference to element types. Co-authored-by: Damien L-G <dalg24@gmail.com> Differential Revision: https://reviews.llvm.org/D153935
This commit is contained in:
parent
4db6c717c4
commit
20c6b9d451
@ -40,7 +40,7 @@ Paper Status
|
||||
|
||||
.. note::
|
||||
|
||||
.. [#note-P0009R18] P0009R18: ``extents``, ``dextents``, ``layout_left``, and ``layout_right`` are implemented.
|
||||
.. [#note-P0009R18] P0009R18: ``extents``, ``dextents``, ``layout_left``, ``layout_right``, and ``default_accessor`` are implemented.
|
||||
.. [#note-P0533R9] P0533R9: ``isfinite``, ``isinf``, ``isnan`` and ``isnormal`` are implemented.
|
||||
.. [#note-P1413R3] P1413R3: ``std::aligned_storage_t`` and ``std::aligned_union_t`` are marked deprecated, but
|
||||
clang doesn't issue a diagnostic for deprecated using template declarations.
|
||||
|
@ -478,6 +478,7 @@ set(files
|
||||
__locale_dir/locale_base_api/bsd_locale_fallbacks.h
|
||||
__locale_dir/locale_base_api/locale_guard.h
|
||||
__mbstate_t.h
|
||||
__mdspan/default_accessor.h
|
||||
__mdspan/extents.h
|
||||
__mdspan/layout_left.h
|
||||
__mdspan/layout_right.h
|
||||
|
66
libcxx/include/__mdspan/default_accessor.h
Normal file
66
libcxx/include/__mdspan/default_accessor.h
Normal file
@ -0,0 +1,66 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
// Kokkos v. 4.0
|
||||
// Copyright (2022) National Technology & Engineering
|
||||
// Solutions of Sandia, LLC (NTESS).
|
||||
//
|
||||
// Under the terms of Contract DE-NA0003525 with NTESS,
|
||||
// the U.S. Government retains certain rights in this software.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___MDSPAN_DEFAULT_ACCESSOR_H
|
||||
#define _LIBCPP___MDSPAN_DEFAULT_ACCESSOR_H
|
||||
|
||||
#include <__config>
|
||||
#include <__type_traits/is_abstract.h>
|
||||
#include <__type_traits/is_array.h>
|
||||
#include <__type_traits/is_convertible.h>
|
||||
#include <__type_traits/remove_const.h>
|
||||
#include <cinttypes>
|
||||
#include <cstddef>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
# pragma GCC system_header
|
||||
#endif
|
||||
|
||||
_LIBCPP_PUSH_MACROS
|
||||
#include <__undef_macros>
|
||||
|
||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||
|
||||
#if _LIBCPP_STD_VER >= 23
|
||||
|
||||
template <class _ElementType>
|
||||
struct default_accessor {
|
||||
static_assert(!is_array_v<_ElementType>, "default_accessor: template argument may not be an array type");
|
||||
static_assert(!is_abstract_v<_ElementType>, "default_accessor: template argument may not be an abstract class");
|
||||
|
||||
using offset_policy = default_accessor;
|
||||
using element_type = _ElementType;
|
||||
using reference = _ElementType&;
|
||||
using data_handle_type = _ElementType*;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr default_accessor() noexcept = default;
|
||||
template <class _OtherElementType>
|
||||
requires(is_convertible_v<_OtherElementType (*)[], element_type (*)[]>)
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr default_accessor(default_accessor<_OtherElementType>) noexcept {}
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr reference access(data_handle_type __p, size_t __i) const noexcept { return __p[__i]; }
|
||||
_LIBCPP_HIDE_FROM_ABI constexpr data_handle_type offset(data_handle_type __p, size_t __i) const noexcept {
|
||||
return __p + __i;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 23
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
||||
#endif // _LIBCPP___MDSPAN_DEFAULT_ACCESSOR_H
|
@ -27,7 +27,7 @@ namespace std {
|
||||
|
||||
// [mdspan.accessor.default], class template default_accessor
|
||||
template<class ElementType>
|
||||
class default_accessor; // not implemented yet
|
||||
class default_accessor;
|
||||
|
||||
// [mdspan.mdspan], class template mdspan
|
||||
template<class ElementType, class Extents, class LayoutPolicy = layout_right,
|
||||
@ -190,6 +190,24 @@ namespace std {
|
||||
};
|
||||
}
|
||||
|
||||
// default_accessor synopsis
|
||||
|
||||
namespace std {
|
||||
template<class ElementType>
|
||||
struct default_accessor {
|
||||
using offset_policy = default_accessor;
|
||||
using element_type = ElementType;
|
||||
using reference = ElementType&;
|
||||
using data_handle_type = ElementType*;
|
||||
|
||||
constexpr default_accessor() noexcept = default;
|
||||
template<class OtherElementType>
|
||||
constexpr default_accessor(default_accessor<OtherElementType>) noexcept;
|
||||
constexpr reference access(data_handle_type p, size_t i) const noexcept;
|
||||
constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;
|
||||
};
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _LIBCPP_MDSPAN
|
||||
@ -197,6 +215,7 @@ namespace std {
|
||||
|
||||
#include <__config>
|
||||
#include <__fwd/mdspan.h>
|
||||
#include <__mdspan/default_accessor.h>
|
||||
#include <__mdspan/extents.h>
|
||||
#include <__mdspan/layout_left.h>
|
||||
#include <__mdspan/layout_right.h>
|
||||
|
@ -1239,6 +1239,7 @@ module std [system] {
|
||||
export *
|
||||
|
||||
module __mdspan {
|
||||
module default_accessor { private header "__mdspan/default_accessor.h" }
|
||||
module extents {
|
||||
private header "__mdspan/extents.h"
|
||||
export array
|
||||
|
@ -23,11 +23,9 @@ export namespace std {
|
||||
using std::layout_right;
|
||||
// using std::layout_stride;
|
||||
|
||||
#if 0
|
||||
// [mdspan.accessor.default], class template default_accessor
|
||||
// [mdspan.accessor.default], class template default_accessor
|
||||
using std::default_accessor;
|
||||
|
||||
// [mdspan.mdspan], class template mdspan
|
||||
using std::mdspan;
|
||||
#endif
|
||||
// using std::mdspan;
|
||||
} // namespace std
|
||||
|
45
libcxx/test/std/containers/views/mdspan/MinimalElementType.h
Normal file
45
libcxx/test/std/containers/views/mdspan/MinimalElementType.h
Normal file
@ -0,0 +1,45 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef TEST_STD_CONTAINERS_VIEWS_MDSPAN_MINIMAL_ELEMENT_TYPE_H
|
||||
#define TEST_STD_CONTAINERS_VIEWS_MDSPAN_MINIMAL_ELEMENT_TYPE_H
|
||||
|
||||
#include<memory>
|
||||
|
||||
// Idiosyncratic element type for mdspan
|
||||
// Make sure we don't assume copyable, default constructible, movable etc.
|
||||
struct MinimalElementType {
|
||||
int val;
|
||||
constexpr MinimalElementType() = delete;
|
||||
constexpr MinimalElementType(const MinimalElementType&) = delete;
|
||||
constexpr explicit MinimalElementType(int v) noexcept : val(v){}
|
||||
constexpr MinimalElementType& operator=(const MinimalElementType&) = delete;
|
||||
};
|
||||
|
||||
// Helper class to create pointer to MinimalElementType
|
||||
template<class T, size_t N>
|
||||
struct ElementPool {
|
||||
constexpr ElementPool() {
|
||||
ptr_ = std::allocator<T>().allocate(N);
|
||||
for (int i = 0; i != N; ++i)
|
||||
std::construct_at(ptr_ + i, 42);
|
||||
}
|
||||
|
||||
constexpr T* get_ptr() { return ptr_; }
|
||||
|
||||
constexpr ~ElementPool() {
|
||||
for (int i = 0; i != N; ++i)
|
||||
std::destroy_at(ptr_ + i);
|
||||
std::allocator<T>().deallocate(ptr_, N);
|
||||
}
|
||||
|
||||
private:
|
||||
T* ptr_;
|
||||
};
|
||||
|
||||
#endif // TEST_STD_CONTAINERS_VIEWS_MDSPAN_MINIMAL_ELEMENT_TYPE_H
|
@ -0,0 +1,49 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// constexpr reference access(data_handle_type p, size_t i) const noexcept;
|
||||
//
|
||||
// Effects: Equivalent to: return p[i];
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
|
||||
template <class T>
|
||||
constexpr void test_access() {
|
||||
ElementPool<std::remove_const_t<T>, 10> data;
|
||||
T* ptr = data.get_ptr();
|
||||
std::default_accessor<T> acc;
|
||||
for(int i = 0; i < 10; i++) {
|
||||
static_assert(std::is_same_v<decltype(acc.access(ptr, i)), typename std::default_accessor<T>::reference>);
|
||||
ASSERT_NOEXCEPT(acc.access(ptr, i));
|
||||
assert(&acc.access(ptr, i) == ptr + i);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
test_access<int>();
|
||||
test_access<const int>();
|
||||
test_access<MinimalElementType>();
|
||||
test_access<const MinimalElementType>();
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// <mdspan>
|
||||
//
|
||||
// Test converting constructor:
|
||||
//
|
||||
// template<class OtherElementType>
|
||||
// constexpr default_accessor(default_accessor<OtherElementType>) noexcept {}
|
||||
//
|
||||
// Constraints: is_convertible_v<OtherElementType(*)[], element_type(*)[]> is true.
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
|
||||
struct Base {};
|
||||
struct Derived: public Base {};
|
||||
|
||||
template <class FromT, class ToT>
|
||||
constexpr void test_conversion() {
|
||||
std::default_accessor<FromT> acc_from;
|
||||
ASSERT_NOEXCEPT(std::default_accessor<ToT>(acc_from));
|
||||
[[maybe_unused]] std::default_accessor<ToT> acc_to(acc_from);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
// default accessor conversion largely behaves like pointer conversion
|
||||
test_conversion<int, int>();
|
||||
test_conversion<int, const int>();
|
||||
test_conversion<const int, const int>();
|
||||
test_conversion<MinimalElementType, MinimalElementType>();
|
||||
test_conversion<MinimalElementType, const MinimalElementType>();
|
||||
test_conversion<const MinimalElementType, const MinimalElementType>();
|
||||
|
||||
// char is convertible to int, but accessors are not
|
||||
static_assert(!std::is_constructible_v<std::default_accessor<int>, std::default_accessor<char>>);
|
||||
// don't allow conversion from const elements to non-const
|
||||
static_assert(!std::is_constructible_v<std::default_accessor<int>, std::default_accessor<const int>>);
|
||||
// MinimalElementType is constructible from int, but accessors should not be convertible
|
||||
static_assert(!std::is_constructible_v<std::default_accessor<MinimalElementType>, std::default_accessor<int>>);
|
||||
// don't allow conversion from const elements to non-const
|
||||
static_assert(!std::is_constructible_v<std::default_accessor<MinimalElementType>, std::default_accessor<const MinimalElementType>>);
|
||||
// don't allow conversion from Base to Derived
|
||||
static_assert(!std::is_constructible_v<std::default_accessor<Derived>, std::default_accessor<Base>>);
|
||||
// don't allow conversion from Derived to Base
|
||||
static_assert(!std::is_constructible_v<std::default_accessor<Base>, std::default_accessor<Derived>>);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// Test default construction:
|
||||
//
|
||||
// constexpr default_accessor() noexcept = default;
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
|
||||
template <class T>
|
||||
constexpr void test_construction() {
|
||||
ASSERT_NOEXCEPT(std::default_accessor<T>{});
|
||||
[[maybe_unused]] std::default_accessor<T> acc;
|
||||
static_assert(std::is_trivially_default_constructible_v<std::default_accessor<T>>);
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
test_construction<int>();
|
||||
test_construction<const int>();
|
||||
test_construction<MinimalElementType>();
|
||||
test_construction<const MinimalElementType>();
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
//
|
||||
// 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
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// template<class ElementType>
|
||||
// class default_accessor;
|
||||
|
||||
// ElementType is required to be a complete object type that is neither an abstract class type nor an array type.
|
||||
|
||||
#include <mdspan>
|
||||
|
||||
class AbstractClass {
|
||||
public:
|
||||
virtual void method() = 0;
|
||||
};
|
||||
|
||||
void not_abstract_class() {
|
||||
// expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}default_accessor: template argument may not be an abstract class}}
|
||||
[[maybe_unused]] std::default_accessor<AbstractClass> acc;
|
||||
}
|
||||
|
||||
void not_array_type() {
|
||||
// expected-error-re@*:* {{{{(static_assert|static assertion)}} failed {{.*}}default_accessor: template argument may not be an array type}}
|
||||
[[maybe_unused]] std::default_accessor<int[5]> acc;
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// constexpr data_handle_type offset(data_handle_type p, size_t i) const noexcept;
|
||||
//
|
||||
// Effects: Equivalent to: return p+i;
|
||||
|
||||
#include <mdspan>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
|
||||
template <class T>
|
||||
constexpr void test_offset() {
|
||||
ElementPool<std::remove_const_t<T>, 10> data;
|
||||
T* ptr = data.get_ptr();
|
||||
std::default_accessor<T> acc;
|
||||
for(int i = 0; i < 10; i++) {
|
||||
static_assert(std::is_same_v<decltype(acc.offset(ptr, i)), typename std::default_accessor<T>::data_handle_type>);
|
||||
ASSERT_NOEXCEPT(acc.offset(ptr, i));
|
||||
assert(acc.offset(ptr, i) == ptr + i);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
test_offset<int>();
|
||||
test_offset<const int>();
|
||||
test_offset<MinimalElementType>();
|
||||
test_offset<const MinimalElementType>();
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// <mdspan>
|
||||
|
||||
// template<class ElementType>
|
||||
// struct default_accessor {
|
||||
// using offset_policy = default_accessor;
|
||||
// using element_type = ElementType;
|
||||
// using reference = ElementType&;
|
||||
// using data_handle_type = ElementType*;
|
||||
// ...
|
||||
// };
|
||||
//
|
||||
// Each specialization of default_accessor is a trivially copyable type that models semiregular.
|
||||
|
||||
|
||||
#include <mdspan>
|
||||
#include <type_traits>
|
||||
#include <concepts>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
#include "../MinimalElementType.h"
|
||||
|
||||
template <class T>
|
||||
void test() {
|
||||
using A = std::default_accessor<T>;
|
||||
ASSERT_SAME_TYPE(typename A::offset_policy, A);
|
||||
ASSERT_SAME_TYPE(typename A::element_type, T);
|
||||
ASSERT_SAME_TYPE(typename A::reference, T&);
|
||||
ASSERT_SAME_TYPE(typename A::data_handle_type, T*);
|
||||
|
||||
static_assert(std::semiregular<A>);
|
||||
static_assert(std::is_trivially_copyable_v<A>);
|
||||
|
||||
LIBCPP_STATIC_ASSERT(std::is_empty_v<A>);
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test<int>();
|
||||
test<const int>();
|
||||
test<MinimalElementType>();
|
||||
test<const MinimalElementType>();
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user