kblib  0.2.3
General utilities library for modern C++
traits.h
Go to the documentation of this file.
1 /* *****************************************************************************
2  * kblib is a general utility library for C++14 and C++17, intended to provide
3  * performant high-level abstractions and more expressive ways to do simple
4  * things.
5  *
6  * Copyright (c) 2021 killerbee
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <https://www.gnu.org/licenses/>.
20  * ****************************************************************************/
21 
32 #ifndef KBLIB_TRAITS_H_INCLUDED_
33 #define KBLIB_TRAITS_H_INCLUDED_
34 
35 #include "fakestd.h"
36 #include "tdecl.h"
37 
38 #include <array>
39 #include <cstring>
40 #include <tuple>
41 #include <type_traits>
42 
43 namespace kblib {
44 
45 // contains_types adapted from code by Maarten Bamelis,
46 // https://stackoverflow.com/a/42581257/1924641
47 
51 template <typename Tuple, typename T>
53 
54 template <typename T, typename U, typename... Ts>
55 struct contains_type<std::tuple<T, Ts...>, U>
56  : contains_type<std::tuple<Ts...>, U> {};
57 
58 template <typename T, typename... Ts>
59 struct contains_type<std::tuple<T, Ts...>, T> : std::true_type {};
60 
61 template <typename T>
62 struct contains_type<std::tuple<>, T> : std::false_type {};
63 
64 template <typename... Ts>
66 
71 template <typename Lhs, typename Rhs>
73 
74 template <typename Tuple, typename T, typename... Ts>
75 struct contains_types<Tuple, std::tuple<T, Ts...>>
76  : std::integral_constant<
77  bool, contains_type<Tuple, T>::value
78  and contains_types<Tuple, std::tuple<Ts...>>::value> {};
79 
80 template <typename Tuple>
81 struct contains_types<Tuple, std::tuple<>> : std::true_type {};
82 
83 template <typename... Ts>
85 
86 template <typename T>
88 
89 template <template <typename...> class Tuple, typename... Ts>
90 struct list_as_tuple<Tuple<Ts...>> {
91  using type = std::tuple<Ts...>;
92 };
93 
94 namespace detail {
95 
104  template <typename T, int N, int... I>
105  KBLIB_NODISCARD constexpr auto trim_array(const T (&arr)[N],
106  std::integer_sequence<int, I...>)
108  return {arr[I]...};
109  }
110 
111 } // namespace detail
112 
119 template <int trim, typename T, int N,
120  typename Indices = std::make_integer_sequence<int, N - trim>>
121 KBLIB_NODISCARD constexpr auto trim_array(const T (&arr)[N])
122  -> std::array<T, N - trim> {
123  return detail::trim_array(arr, Indices{});
124 }
125 
134 template <int N, typename Indices = std::make_integer_sequence<int, N - 1>>
135 KBLIB_NODISCARD constexpr auto remove_null_terminator(const char (&arr)[N])
136  -> std::array<char, N - 1> {
137  return detail::trim_array(arr, Indices{});
138 }
139 
140 template <typename T>
141 struct is_unbounded_array : std::false_type {};
142 template <typename T>
143 struct is_unbounded_array<T[]> : std::true_type {};
144 
145 template <typename T>
146 struct is_bounded_array : std::false_type {};
147 template <typename T, std::size_t N>
148 struct is_bounded_array<T[N]> : std::true_type {};
149 
150 template <typename T>
155 using alias = T;
156 
160 template <typename, typename T>
161 struct ignore {
162  using type = T;
163 };
168 template <typename U, typename T>
169 using ignore_t = typename ignore<U, T>::type;
170 
181 template <typename T, typename F>
182 KBLIB_NODISCARD auto byte_cast(F v) noexcept -> T {
183  static_assert(
184  sizeof(T) == sizeof(F),
185  "Source and destination types for byte_cast must be the same size.");
186  static_assert(std::is_trivially_copyable<T>::value
187  and std::is_trivially_copyable<F>::value,
188  "Source and destination types for byte_cast must be trivially "
189  "copyable.");
190  T ret{};
191  std::memcpy(&ret, &v, sizeof(T));
192  return ret;
193 }
194 
195 namespace detail {
196 
197  template <typename C, typename = decltype(std::declval<C&>().resize(0))>
198  auto calc_resizable(int) noexcept -> std::true_type;
199 
200  template <typename C, int = std::tuple_size<C>::value>
201  auto calc_resizable(int) noexcept -> std::false_type;
202 
203  template <typename>
204  auto calc_resizable(...) noexcept -> std::false_type;
205 
206 } // namespace detail
207 
208 // Note that when a type that is not resizable, but also doesn't have a
209 // constexpr size, is passed, there is a hard error.
213 template <typename C>
214 KBLIB_CONSTANT_V is_resizable_v = decltype(detail::calc_resizable<C>(0))::value;
215 
216 template <typename C>
218 
219 template <typename C, typename = void>
221 
222 template <typename C>
224  has_reserve_v<C, void_t<decltype(std::declval<C&>().reserve(0))>> = true;
225 
229 template <typename C>
230 struct has_reserve : bool_constant<has_reserve_v<C>> {};
231 
238 template <typename C, typename std::enable_if<has_reserve_v<C>, int>::type = 0>
239 auto try_reserve(C& c, std::size_t s) noexcept(noexcept(c.reserve(s))) -> void {
240  c.reserve(s);
241  return;
242 }
243 
250 template <typename C,
251  typename std::enable_if<not has_reserve_v<C>, int>::type = 0>
252 auto try_reserve(C&, std::size_t) noexcept -> void {
253  return;
254 }
255 
260 template <typename C, typename = void>
262 
263 template <typename C>
265  is_contiguous_v<C, void_t<decltype(std::declval<C&>().data())>> = true;
266 
267 template <typename C>
268 struct is_contiguous : bool_constant<is_contiguous_v<C>> {};
269 
270 template <typename T>
271 struct class_of;
272 
273 template <typename T, typename M>
274 struct class_of<M T::*> {
275  using type = T;
276 };
277 
278 template <typename T>
279 using class_of_t = typename class_of<T>::type;
280 
281 #if __cpp_nontype_template_parameter_auto
282 
283 template <auto M>
284 using class_t = typename class_of<decltype(M)>::type;
285 
286 #endif
287 
288 template <typename T>
289 struct member_of;
290 
291 template <typename T, typename M>
292 struct member_of<M T::*> {
293  using type = M;
294 };
295 
296 template <typename T>
298 
299 #if __cpp_nontype_template_parameter_auto
304 template <typename, auto M>
305 using member_t = member_of_t<decltype(M)>;
306 #endif
307 
308 template <typename F>
309 struct return_type;
310 
311 template <typename R, typename... Args>
312 struct return_type<R(Args...)> : meta_type<R> {};
313 
314 template <typename R, typename... Args>
315 struct return_type<R(Args...) const> : meta_type<R> {};
316 
317 template <typename R, typename... Args>
318 struct return_type<R(Args...) volatile> : meta_type<R> {};
319 
320 template <typename R, typename... Args>
321 struct return_type<R(Args...) const volatile> : meta_type<R> {};
322 
323 template <typename T>
324 struct exists : std::true_type {};
325 
326 template <typename T, typename = void>
327 struct is_input_iterator : std::false_type {};
328 
329 template <typename T>
331  T, void_if_t<std::is_base_of<
332  std::input_iterator_tag,
333  typename std::iterator_traits<T>::iterator_category>::value>>
334  : std::true_type {};
335 
336 template <typename T>
338 
339 template <typename T, typename = void>
340 struct is_forward_iterator : std::false_type {};
341 
342 template <typename T>
344  T, void_if_t<std::is_base_of<
345  std::forward_iterator_tag,
346  typename std::iterator_traits<T>::iterator_category>::value>>
347  : std::true_type {};
348 
349 template <typename T>
351 
352 template <typename T, typename = void>
353 struct is_bidirectional_iterator : std::false_type {};
354 
355 template <typename T>
357  T, void_if_t<std::is_base_of<
358  std::bidirectional_iterator_tag,
359  typename std::iterator_traits<T>::iterator_category>::value>>
360  : std::true_type {};
361 
362 template <typename T>
365 
366 template <typename T, typename = void>
367 struct is_random_access_iterator : std::false_type {};
368 
369 template <typename T>
371  T, void_if_t<std::is_base_of<
372  std::random_access_iterator_tag,
373  typename std::iterator_traits<T>::iterator_category>::value>>
374  : std::true_type {};
375 
376 template <typename T>
379 
384 template <typename Range, typename = void>
386 template <typename T, std::size_t N>
387 struct iterator_type_for<T[N], void> {
388  using type = T*;
389 };
390 template <typename Range>
391 struct iterator_type_for<Range,
392  void_t<decltype(begin(std::declval<Range&>()))>> {
393  using type = decltype(begin(std::declval<Range&>()));
394 };
395 
396 template <typename Range>
398 
399 template <typename Range, typename = void>
400 struct is_iterable : std::false_type {};
401 
402 template <typename Range>
403 struct is_iterable<Range, void_if_t<is_input_iterator<decltype(
404  begin(std::declval<Range&>()))>::value>>
405  : std::true_type {};
406 
407 template <typename T, std::size_t N>
408 struct is_iterable<T[N], void> : std::true_type {};
409 template <typename T, std::size_t N>
410 struct is_iterable<T (&)[N], void> : std::true_type {};
411 
412 template <typename T>
414 
415 template <typename T, typename = void>
416 struct is_iterator : std::false_type {};
417 
418 template <typename T>
419 struct is_iterator<
420  T, void_t<decltype(*std::declval<T&>(), void(), ++std::declval<T&>())>>
421  : std::true_type {};
422 
423 template <typename T>
425 
430 template <typename T>
431 KBLIB_CONSTANT_V is_reference_v = std::is_reference<T>::value;
432 
437 template <typename T>
438 using remove_reference_t = typename std::remove_reference<T>::type;
439 
443 template <typename CharT = char>
445 
446 template <typename T, T V>
448  operator T() const noexcept { return V; }
449  static constexpr T value = V;
450 };
451 
452 #if __cpp_nontype_template_parameter_auto
453 
454 template <auto V>
455 using type_constant_for = type_constant<decltype(V), V>;
456 
457 #endif
458 
459 template <typename T>
460 struct is_aliasing_type : std::false_type {};
461 template <>
462 struct is_aliasing_type<char> : std::true_type {};
463 template <>
464 struct is_aliasing_type<unsigned char> : std::true_type {};
465 #if __cpp_lib_byte
466 template <>
467 struct is_aliasing_type<std::byte> : std::true_type {};
468 #endif
469 
470 template <typename T>
472 
473 } // namespace kblib
474 
475 #endif // KBLIB_TRAITS_H_INCLUDED_
This header provides some features of C++17 <type_traits> and other headers for C++14,...
constexpr auto trim_array(const T(&arr)[N], std::integer_sequence< int, I... >) -> std::array< T, std::integer_sequence< int, I... >::size()>
Truncates an array to its first N elements.
Definition: traits.h:105
auto calc_resizable(int) noexcept -> std::true_type
typename make_void< Ts... >::type void_t
Definition: fakestd.h:178
constexpr auto size(const C &c) -> decltype(c.size())
Definition: fakestd.h:365
The main namespace in which all entities from kblib are defined.
Definition: algorithm.h:44
constexpr auto trim_array(const T(&arr)[N]) -> std::array< T, N - trim >
Truncates the last trim elements from an array.
Definition: traits.h:121
KBLIB_CONSTANT_V is_input_iterator_v
Definition: traits.h:337
typename ignore< U, T >::type ignore_t
An alias for ignore<U, T>::type.
Definition: traits.h:169
KBLIB_CONSTANT_V contains_type_v
Definition: traits.h:65
KBLIB_CONSTANT_V is_iterable_v
Definition: traits.h:413
typename std::remove_reference< T >::type remove_reference_t
Abbreviated name for std::remove_reference<T>::type for C++14.
Definition: traits.h:438
typename iterator_type_for< Range >::type iterator_type_for_t
Definition: traits.h:397
KBLIB_CONSTANT_V is_reference_v
Abbreviated name for std::is_reference<T>::value for C++14.
Definition: traits.h:431
auto try_reserve(C &c, std::size_t s) noexcept(noexcept(c.reserve(s))) -> void
Attempt to reserve capacity in a container. No-op if unsupported.
Definition: traits.h:239
KBLIB_CONSTANT_V is_iterator_v
Definition: traits.h:424
KBLIB_CONSTANT_V contains_types_v
Definition: traits.h:84
typename member_of< T >::type member_of_t
Definition: traits.h:297
KBLIB_CONSTANT_V is_forward_iterator_v
Definition: traits.h:350
T alias
A simple identity alias for simplifying some compound type declarations, such as function pointers.
Definition: traits.h:155
KBLIB_CONSTANT_V is_resizable_v
Definition: traits.h:214
constexpr auto remove_null_terminator(const char(&arr)[N]) -> std::array< char, N - 1 >
Creates an array of only the meaningful characters in a string literal, and not the null terminator.
Definition: traits.h:135
KBLIB_CONSTANT_V is_random_access_iterator_v
Definition: traits.h:378
KBLIB_CONSTANT_V is_aliasing_type_v
Definition: traits.h:471
std::integral_constant< bool, v > bool_constant
Definition: fakestd.h:64
typename void_if< b >::type void_if_t
Definition: fakestd.h:512
KBLIB_CONSTANT_V is_bidirectional_iterator_v
Definition: traits.h:364
typename class_of< T >::type class_of_t
Definition: traits.h:279
KBLIB_CONSTANT_V is_contiguous_v
Type trait to determine if a container is contiguous.
Definition: traits.h:261
KBLIB_CONSTANT_V has_reserve_v
Definition: traits.h:220
auto byte_cast(F v) noexcept -> T
Creates a T with the same object representation as the given F.
Definition: traits.h:182
KBLIB_CONSTANT auto eof
Names the EOF value for the given character type in std::char_traits.
Definition: traits.h:444
Definition: bits.h:714
Determines if T is a type in Tuple, which must be a std::tuple.
Definition: traits.h:52
Determines if Lhs contains all of the types in Rhs, where both are std::tuples.
Definition: traits.h:72
True if and only if C contains an accessible reserve() member.
Definition: traits.h:230
Ignores its first template argument entirely, and returns its second.
Definition: traits.h:161
Type trait that determines the iterator type for a range.
Definition: traits.h:385
Provides macros and basic templates used by the rest of kblib.
#define KBLIB_CONSTANT
Definition: tdecl.h:98
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Definition: tdecl.h:81
#define KBLIB_CONSTANT_V
Definition: tdecl.h:99