metaprogramming.h Source File

CPP API: metaprogramming.h Source File
metaprogramming.h
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2020-2026 MEmilio
3 *
4 * Authors: Daniel Abele
5 *
6 * Contact: Martin J. Kuehn <Martin.Kuehn@DLR.de>
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20 #ifndef MIO_UTILS_METAPROGRAMMING_H
21 #define MIO_UTILS_METAPROGRAMMING_H
22 
23 #include <type_traits>
24 #include <utility>
25 
26 namespace ad
27 {
28 namespace internal
29 {
30 // Forward declaration of the AD type template
31 template <class Value, class Tape>
32 struct active_type;
33 } // namespace internal
34 } // namespace ad
35 
36 namespace mio
37 {
38 
39 namespace details
40 {
41 //non-copyable but trivally constructible and moveable type
42 struct NoCopy {
43  NoCopy(const NoCopy&) = delete;
44  NoCopy() = default;
45  NoCopy(NoCopy&&) = default;
46  NoCopy& operator=(const NoCopy&) = delete;
47  NoCopy& operator=(NoCopy&&) = default;
48 };
49 
50 //trivially constructible, copyable, moveable type
51 struct Empty {
52 };
53 } // namespace details
54 
56 template <class T>
57 using is_small_integral = std::integral_constant<bool, (std::is_integral_v<T> && sizeof(T) <= 4)>;
59 template <class T>
60 using is_64bit_integral = std::integral_constant<bool, (std::is_integral_v<T> && sizeof(T) == 8)>;
61 
70 template <bool Cond>
71 using not_copyable_if = std::conditional<Cond, details::NoCopy, details::Empty>;
72 
77 template <bool Cond>
79 
80 namespace details
81 {
82 
89 template <std::size_t Index, class Head, class... Tail>
91  using type = typename type_at_index_impl<Index - 1, Tail...>::type;
92 };
93 template <class Head, class... Tail>
94 struct type_at_index_impl<0, Head, Tail...> {
95  using type = Head;
96 };
99 } // namespace details
100 
106 template <std::size_t Index, class... Types>
108  static_assert(Index < sizeof...(Types), "Index is too large for the list Types.");
109  using type = typename details::type_at_index_impl<Index, Types...>::type;
110 };
111 
117 template <std::size_t Index, class... Types>
118 using type_at_index_t = typename type_at_index<Index, Types...>::type;
119 
120 namespace details
121 {
122 
131 template <std::size_t Size, class Type>
132 constexpr std::size_t index_of_impl()
133 {
134  // this works both as an overload for empty lists as well as a "not found"
135  return Size;
136 }
137 template <std::size_t Size, class Type, class Head, class... Tail>
138 constexpr std::size_t index_of_impl()
139 {
140  // check if the type matches, otherwise call itself, omitting Head
141  // this is significantly cheaper to compile compared to using an index and carrying the entire list,
142  // as that needs additional work for looking up "Types[Index]", e.g. through type_at_index
143  if constexpr (std::is_same_v<Type, Head>) {
144  return Size - sizeof...(Tail) - 1;
145  }
146  else {
147  return index_of_impl<Size, Type, Tail...>();
148  }
149 }
152 } // namespace details
153 
159 template <class Type, class... Types>
161  : std::conditional_t<(details::index_of_impl<sizeof...(Types), Type, Types...>() < sizeof...(Types)),
162  std::true_type, std::false_type> {
163 };
164 
170 template <class Type, class... Types>
171 constexpr bool is_type_in_list_v = is_type_in_list<Type, Types...>::value;
172 
179 template <class Type, class... Types>
180 struct index_of_type {
181  static constexpr std::size_t value = details::index_of_impl<sizeof...(Types), Type, Types...>();
182  static_assert(value < sizeof...(Types), "Type is not contained in given list.");
183 };
184 
190 template <class Type, class... Types>
191 constexpr std::size_t index_of_type_v = index_of_type<Type, Types...>::value;
192 
197 template <class... Types>
198 struct has_duplicates {
199 private:
205  template <std::size_t... Indices>
206  static constexpr bool has_duplicates_impl(std::index_sequence<Indices...>)
207  {
208  // index_of_type_v will always be equal to the index of the first occurance of a type,
209  // while Indices contains its actual index. Hence, if there is any mismatch, then there is a duplicate.
210  return ((index_of_type_v<Types, Types...> != Indices) || ...);
211  }
212 
213 public:
214  static constexpr bool value = has_duplicates_impl(std::make_index_sequence<sizeof...(Types)>{});
215 };
216 
222 template <class... Types>
223 constexpr bool has_duplicates_v = has_duplicates<Types...>::value;
224 
230 template <class T, class = void>
231 struct is_ad_type : public std::false_type {
232 };
233 
234 template <class Value, class Tape>
235 struct is_ad_type<ad::internal::active_type<Value, Tape>> : public std::true_type {
236 };
237 
238 template <class T>
239 constexpr bool is_ad_type_v = is_ad_type<T>::value;
242 } // namespace mio
243 
244 #endif // MIO_UTILS_METAPROGRAMMING_H
An Index with more than one template parameter combines several Index objects.
Definition: index.h:181
Definition: ad.h:31
constexpr std::size_t index_of_impl()
Recursively searches the list (Head, Tail...) for Type.
Definition: metaprogramming.h:132
A collection of classes to simplify handling of matrix shapes in meta programming.
Definition: models/abm/analyze_result.h:30
typename not_copyable_if< Cond >::type not_copyable_if_t
equivalent to not_copyable_if<Cond>::type.
Definition: metaprogramming.h:78
std::conditional< Cond, details::NoCopy, details::Empty > not_copyable_if
Defines a type that is not copy constructible or assignable if the specified condition is true.
Definition: metaprogramming.h:71
typename type_at_index< Index, Types... >::type type_at_index_t
The type at the Index-th position in the list Types.
Definition: metaprogramming.h:118
std::integral_constant< bool,(std::is_integral_v< T > &&sizeof(T)==8)> is_64bit_integral
Bool constant to check whether T is an integral type of 64 bits. Used for Json library.
Definition: metaprogramming.h:60
std::integral_constant< bool,(std::is_integral_v< T > &&sizeof(T)<=4)> is_small_integral
Bool constant to check whether T is an integral type of 32 bits or less. Used for Json library.
Definition: metaprogramming.h:57
Definition: metaprogramming.h:51
Definition: metaprogramming.h:42
NoCopy & operator=(NoCopy &&)=default
NoCopy(const NoCopy &)=delete
NoCopy(NoCopy &&)=default
NoCopy & operator=(const NoCopy &)=delete
Head type
Definition: metaprogramming.h:95
Get the type at position Index of list (Head, Tail...).
Definition: metaprogramming.h:90
typename type_at_index_impl< Index - 1, Tail... >::type type
Definition: metaprogramming.h:91
Tests whether Type is in the list Types.
Definition: metaprogramming.h:162
Finds the type at the Index-th position in the list Types.
Definition: metaprogramming.h:107
typename details::type_at_index_impl< Index, Types... >::type type
Definition: metaprogramming.h:109