TRIQS/nda 1.3.0
Multi-dimensional array library for C++
Loading...
Searching...
No Matches
concepts.hpp
Go to the documentation of this file.
1// Copyright (c) 2020--present, The Simons Foundation
2// This file is part of TRIQS/nda and is licensed under the Apache License, Version 2.0.
3// SPDX-License-Identifier: Apache-2.0
4// See LICENSE in the root of this distribution for details.
5
10
11#pragma once
12
14#include "./traits.hpp"
15
16#include <array>
17#include <concepts>
18#include <type_traits>
19#include <utility>
20
21namespace nda {
22
27
28 // clang has full support for "lambdas in unevaluated context" only for versions >= 17.
29#ifndef __clang__
30
31 // clang-format off
41 template <typename A, int R>
42 concept CallableWithLongs = requires(A const &a) {
43 // if decltype is not present, the concept will fail to compile for an A for which the a(Is...) is not well formed
44 []<auto... Is>(std::index_sequence<Is...>, auto const &aa) -> decltype(aa(long(Is)...)) {return aa(long(Is)...);}
45 (std::make_index_sequence<R>{}, a);
46 };
47 // clang-format on
48
49#else
50
51 namespace detail {
52
53 // Helper function declaration to check if A can be called with R long arguments.
54 template <auto... Is, typename A>
55 auto call_on_R_longs(std::index_sequence<Is...>, A const &a) -> decltype(a((long{Is})...)); // no impl needed
56
57 } // namespace detail
58
68 template <typename A, int R>
69 concept CallableWithLongs = requires(A const &a) {
70 { detail::call_on_R_longs(std::make_index_sequence<R>{}, a) };
71 };
72
73#endif // __clang__
74
75 namespace detail {
76
77 // Check if T is of type std::array<long, R> for arbitrary array sizes R.
78 template <typename T>
79 constexpr bool is_std_array_of_long_v = false;
80
81 // Specialization of nda::detail::is_std_array_of_long_v for cvref types.
82 template <typename T>
83 requires(!std::is_same_v<T, std::remove_cvref_t<T>>)
84 constexpr bool is_std_array_of_long_v<T> = is_std_array_of_long_v<std::remove_cvref_t<T>>;
85
86 // Specialization of nda::detail::is_std_array_of_long_v for std::array<long, R>.
87 template <auto R>
88 constexpr bool is_std_array_of_long_v<std::array<long, R>> = true;
89
90 } // namespace detail
91
100 template <class T>
101 concept StdArrayOfLong = detail::is_std_array_of_long_v<T>;
102
107 template <typename S>
109
114 template <typename S>
116
125 template <typename T, template <typename...> class TMPLT>
127
136 template <typename T, typename... Us>
137 concept AnyOf = is_any_of<T, Us...>;
138
140
141 namespace mem {
142
147
149 // Forward declarations.
150 struct blk_t;
151 enum class AddressSpace;
153
165 template <typename A>
166 concept Allocator = requires(A &a) {
167 { a.allocate(size_t{}) } noexcept -> std::same_as<blk_t>;
168 { a.allocate_zero(size_t{}) } noexcept -> std::same_as<blk_t>;
169 { a.deallocate(std::declval<blk_t>()) } noexcept;
170 { A::address_space } -> std::same_as<AddressSpace const &>;
171 };
172
183 template <typename H, typename T = typename std::remove_cvref_t<H>::value_type>
184 concept Handle = requires(H const &h) {
185 requires std::is_same_v<typename std::remove_cvref_t<H>::value_type, T>;
186 { h.is_null() } noexcept -> std::same_as<bool>;
187 { h.data() } noexcept -> std::same_as<T *>;
188 { H::address_space } -> std::same_as<AddressSpace const &>;
189 };
190
200 template <typename H, typename T = typename std::remove_cvref_t<H>::value_type>
201 concept OwningHandle = Handle<H, T> and requires(H const &h) {
202 requires not std::is_const_v<typename std::remove_cvref_t<H>::value_type>;
203 { h.size() } noexcept -> std::same_as<long>;
204 };
205
207
208 } // namespace mem
209
214
229 template <typename A>
230 concept Array = requires(A const &a) {
231 { a.shape() } -> StdArrayOfLong;
232 { a.size() } -> std::same_as<long>;
234 };
235
247 template <typename A, typename A_t = std::remove_cvref_t<A>>
248 concept MemoryArray = Array<A> && requires(A &a) {
249 typename A_t::storage_t;
251 typename A_t::value_type;
252 {
253 a.data()
254 } -> std::same_as<std::conditional_t<std::is_const_v<std::remove_reference_t<A>> || std::is_const_v<typename A_t::value_type>,
256 { a.indexmap().strides() } -> StdArrayOfLong;
257 };
258
265 template <typename A, int R>
266 concept ArrayOfRank = Array<A> and (get_rank<A> == R);
267
274 template <typename A, int R>
276
281 template <typename AS>
283
289 template <typename M>
291
297 template <typename V>
299
305 template <typename M>
307
313 template <typename V>
315
324 template <typename A, typename B>
325 concept ArrayInitializer = requires(A const &a) {
326 { a.shape() } -> StdArrayOfLong;
327 typename std::remove_cvref_t<A>::value_type;
328 requires MemoryArray<B> && requires(B &b) { a.invoke(b); }; // FIXME not perfect: it should accept any layout ??
329 };
330
331 // FIXME : We should not need this ... Only used once...
338 template <typename A, typename U>
339 concept HasValueTypeConstructibleFrom = Array<A> and (std::is_constructible_v<U, get_value_t<A>>);
340
342
343} // namespace nda
True iif T is same_as any of the Us.
Definition concepts.hpp:137
Check if a given type satisfies the array concept.
Definition concepts.hpp:230
Check if a given type satisfies the array initializer concept for a given nda::MemoryArray type.
Definition concepts.hpp:325
Check if a given type is an nda::Array of a certain rank.
Definition concepts.hpp:266
Check if if a given type is either an nda::Array or an nda::Scalar.
Definition concepts.hpp:282
Check if a given type can be called with a certain number of long arguments.
Definition concepts.hpp:42
Check if a given type is either a double or complex type.
Definition concepts.hpp:115
Check if a given type is constructible from the value type of a given nda::Array type.
Definition concepts.hpp:339
Check if a given type is an instantiation of some other template type.
Definition concepts.hpp:126
Check if a given type is a matrix, i.e. an nda::ArrayOfRank<2>.
Definition concepts.hpp:290
Check if a given type satisfies the memory array concept.
Definition concepts.hpp:248
Check if a given type is an nda::MemoryArray of a certain rank.
Definition concepts.hpp:275
Check if a given type is a memory matrix, i.e. an nda::MemoryArrayOfRank<2>.
Definition concepts.hpp:306
Check if a given type is a memory vector, i.e. an nda::MemoryArrayOfRank<1>.
Definition concepts.hpp:314
Check if a given type is either an arithmetic or complex type.
Definition concepts.hpp:108
Check if a given type is of type std::array<long, R> for some arbitrary R.
Definition concepts.hpp:101
Check if a given type is a vector, i.e. an nda::ArrayOfRank<1>.
Definition concepts.hpp:298
Check if a given type satisfies the allocator concept.
Definition concepts.hpp:166
Check if a given type satisfies the memory handle concept.
Definition concepts.hpp:184
Check if a given type satisfies the owning memory handle concept.
Definition concepts.hpp:201
constexpr int get_rank
Constexpr variable that specifies the rank of an nda::Array or of a contiguous 1-dimensional range.
Definition traits.hpp:125
std::decay_t< decltype(get_first_element(std::declval< A const >()))> get_value_t
Get the value type of an array/view or a scalar type.
Definition traits.hpp:181
AddressSpace
Enum providing identifiers for the different memory address spaces.
constexpr bool is_instantiation_of_v
Constexpr variable that is true if type T is an instantiation of TMPLT (see nda::is_instantiation_of)...
Definition traits.hpp:48
static constexpr bool is_any_of
Constexpr variable that is true if type T is contained in the parameter pack Ts.
Definition traits.hpp:52
constexpr bool is_double_or_complex_v
Constexpr variable that is true if type T is a std::complex type or a double type.
Definition traits.hpp:87
constexpr bool is_scalar_v
Constexpr variable that is true if type S is a scalar type, i.e. arithmetic or complex.
Definition traits.hpp:68
Provides missing concepts for older compiler versions.
Provides type traits for the nda library.