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
43namespace KBLIB_NS {
44
45// contains_types adapted from code by Maarten Bamelis,
46// https://stackoverflow.com/a/42581257/1924641
47
51template <typename Tuple, typename T>
53
54template <typename T, typename U, typename... Ts>
55struct contains_type<std::tuple<T, Ts...>, U>
56 : contains_type<std::tuple<Ts...>, U> {};
57
58template <typename T, typename... Ts>
59struct contains_type<std::tuple<T, Ts...>, T> : std::true_type {};
60
61template <typename T>
62struct contains_type<std::tuple<>, T> : std::false_type {};
63
64template <typename... Ts>
66
71template <typename Lhs, typename Rhs>
73
74template <typename Tuple, typename T, typename... Ts>
75struct 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
80template <typename Tuple>
81struct contains_types<Tuple, std::tuple<>> : std::true_type {};
82
83template <typename... Ts>
85
86template <typename T>
88
89template <template <typename...> class Tuple, typename... Ts>
90struct list_as_tuple<Tuple<Ts...>> {
91 using type = std::tuple<Ts...>;
92};
93
94namespace 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
119template <int trim, typename T, int N,
120 typename Indices = std::make_integer_sequence<int, N - trim>>
121KBLIB_NODISCARD constexpr auto trim_array(const T (&arr)[N])
122 -> std::array<T, N - trim> {
123 return detail::trim_array(arr, Indices{});
124}
125
134template <int N, typename Indices = std::make_integer_sequence<int, N - 1>>
135KBLIB_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
140template <typename T>
141struct is_unbounded_array : std::false_type {};
142template <typename T>
143struct is_unbounded_array<T[]> : std::true_type {};
144
145template <typename T>
146struct is_bounded_array : std::false_type {};
147template <typename T, std::size_t N>
148struct is_bounded_array<T[N]> : std::true_type {};
149
150template <typename T>
155using alias = T;
156
160template <typename, typename T>
161struct ignore {
162 using type = T;
163};
168template <typename U, typename T>
170
181template <typename T, typename F>
182KBLIB_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
195namespace 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.
213template <typename C>
214KBLIB_CONSTANT_V is_resizable_v = decltype(detail::calc_resizable<C>(0))::value;
215
216template <typename C>
218
219template <typename C, typename = void>
221
222template <typename C>
224 has_reserve_v<C, void_t<decltype(std::declval<C&>().reserve(0))>> = true;
225
229template <typename C>
230struct has_reserve : bool_constant<has_reserve_v<C>> {};
231
238template <typename C, typename std::enable_if<has_reserve_v<C>, int>::type = 0>
239auto try_reserve(C& c, std::size_t s) noexcept(noexcept(c.reserve(s))) -> void {
240 c.reserve(s);
241 return;
242}
243
250template <typename C,
251 typename std::enable_if<not has_reserve_v<C>, int>::type = 0>
252auto try_reserve(C&, std::size_t) noexcept -> void {
253 return;
254}
255
260template <typename C, typename = void>
262
263template <typename C>
265 is_contiguous_v<C, void_t<decltype(std::declval<C&>().data())>> = true;
266
267template <typename C>
268struct is_contiguous : bool_constant<is_contiguous_v<C>> {};
269
270template <typename T>
271struct class_of;
272
273template <typename T, typename M>
274struct class_of<M T::*> {
275 using type = T;
276};
277
278template <typename T>
280
281#if __cpp_nontype_template_parameter_auto
282
283template <auto M>
284using class_t = typename class_of<decltype(M)>::type;
285
286#endif
287
288template <typename T>
290
291template <typename T, typename M>
292struct member_of<M T::*> {
293 using type = M;
294};
295
296template <typename T>
298
299#if __cpp_nontype_template_parameter_auto
304template <typename, auto M>
305using member_t = member_of_t<decltype(M)>;
306#endif
307
308template <typename F>
310
311template <typename R, typename... Args>
312struct return_type<R(Args...)> : meta_type<R> {};
313
314template <typename R, typename... Args>
315struct return_type<R(Args...) const> : meta_type<R> {};
316
317template <typename R, typename... Args>
318struct return_type<R(Args...) volatile> : meta_type<R> {};
319
320template <typename R, typename... Args>
321struct return_type<R(Args...) const volatile> : meta_type<R> {};
322
323template <typename T>
324struct exists : std::true_type {};
325
326template <typename T, typename = void>
327struct is_input_iterator : std::false_type {};
328
329template <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
336template <typename T>
338
339template <typename T, typename = void>
340struct is_forward_iterator : std::false_type {};
341
342template <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
349template <typename T>
351
352template <typename T, typename = void>
353struct is_bidirectional_iterator : std::false_type {};
354
355template <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
362template <typename T>
365
366template <typename T, typename = void>
367struct is_random_access_iterator : std::false_type {};
368
369template <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
376template <typename T>
379
384template <typename Range, typename = void>
386template <typename T, std::size_t N>
387struct iterator_type_for<T[N], void> {
388 using type = T*;
389};
390template <typename Range>
391struct iterator_type_for<Range,
392 void_t<decltype(begin(std::declval<Range&>()))>> {
393 using type = decltype(begin(std::declval<Range&>()));
394};
395
396template <typename Range>
398
399template <typename Range, typename = void>
400struct is_iterable : std::false_type {};
401
402template <typename Range>
404 begin(std::declval<Range&>()))>::value>>
405 : std::true_type {};
406
407template <typename T, std::size_t N>
408struct is_iterable<T[N], void> : std::true_type {};
409template <typename T, std::size_t N>
410struct is_iterable<T (&)[N], void> : std::true_type {};
411
412template <typename T>
414
415template <typename T, typename = void>
416struct is_iterator : std::false_type {};
417
418template <typename T>
420 T, void_t<decltype(*std::declval<T&>(), void(), ++std::declval<T&>())>>
421 : std::true_type {};
422
423template <typename T>
425
430template <typename T>
431KBLIB_CONSTANT_V is_reference_v = std::is_reference<T>::value;
432
437template <typename T>
438using remove_reference_t = typename std::remove_reference<T>::type;
439
443template <typename CharT = char>
445
446template <typename T, T V>
448 constexpr operator T() const noexcept { return V; }
449 static constexpr T value = V;
450};
451
452#if __cpp_nontype_template_parameter_auto
453
454template <auto V>
455using type_constant_for = type_constant<decltype(V), V>;
456
457#endif
458
459template <typename T>
460struct is_aliasing_type : std::false_type {};
461template <>
462struct is_aliasing_type<char> : std::true_type {};
463template <>
464struct is_aliasing_type<unsigned char> : std::true_type {};
465#if __cpp_lib_byte
466template <>
467struct is_aliasing_type<std::byte> : std::true_type {};
468#endif
469
470template <typename T>
472
473} // namespace KBLIB_NS
474
475#endif // KBLIB_TRAITS_H_INCLUDED_
This header provides some features of C++17 <type_traits> and other headers for C++14,...
auto calc_resizable(...) noexcept -> std::false_type
typename make_void< Ts... >::type void_t
Definition: fakestd.h:186
constexpr auto size(const C &c) -> decltype(c.size())
Definition: fakestd.h:373
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:71
typename void_if< b >::type void_if_t
Definition: fakestd.h:520
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:721
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:137
#define KBLIB_NS
Definition: tdecl.h:113
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Definition: tdecl.h:129
#define KBLIB_CONSTANT_V
Definition: tdecl.h:138