C++ Essence Library 0.1.0
A Utility Library for Modern C++ Programming
Loading...
Searching...
No Matches
type_list.hpp
1/*
2 * Copyright (c) 2024 The RefValue Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#pragma once
24
25#include <cstddef>
26#include <limits>
27#include <tuple>
28#include <type_traits>
29#include <utility>
30
31namespace essence {
32 template <typename... Ts>
33 struct type_list {
34 static constexpr std::size_t size = sizeof...(Ts);
35 };
36
37 template <typename T>
38 struct is_type_list_like : std::false_type {};
39
40 template <template <typename...> typename List, typename... Ts>
41 struct is_type_list_like<List<Ts...>> : std::true_type {};
42
43 template <typename T>
44 inline constexpr bool is_type_list_like_v = is_type_list_like<T>::value;
45
46 template <typename T>
47 concept type_list_like = is_type_list_like_v<T>;
48
49 template <typename List>
50 struct type_list_size {};
51
52 template <template <typename...> typename List, typename... Ts>
53 struct type_list_size<List<Ts...>> {
54 static constexpr std::size_t value = sizeof...(Ts);
55 };
56
57 template <typename List>
58 inline constexpr std::size_t type_list_size_v = type_list_size<List>::value;
59
60 template <typename List, std::size_t I>
61 struct at {};
62
63 template <template <typename...> typename List, typename... Ts, std::size_t I>
64 struct at<List<Ts...>, I> {
65 using type = std::tuple_element_t<I, std::tuple<Ts...>>;
66 };
67
68 template <typename List, std::size_t I>
69 using at_t = typename at<List, I>::type;
70
71 template <typename List, typename T>
72 struct append {};
73
74 template <template <typename...> typename List, typename... Ts, typename T>
75 struct append<List<Ts...>, T> {
76 using type = List<Ts..., T>;
77 };
78
79 template <typename List, typename T>
80 using append_t = typename append<List, T>::type;
81
82 template <type_list_like List, typename Callable>
83 constexpr auto for_each_as_values(Callable&& handler) {
84 auto tuple = std::forward_as_tuple(std::forward<Callable>(handler));
85
86 return
87 [&]<template <typename...> typename ConcreteList, typename... Ts>(std::type_identity<ConcreteList<Ts...>>) {
88 return std::get<0>(std::move(tuple))(std::type_identity<Ts>{}...);
89 }(std::type_identity<List>{});
90 }
91
92 template <type_list_like List, auto Predicate>
93 struct index_if {
94 static constexpr auto value = for_each_as_values<List>([]<typename... Ts>(std::type_identity<Ts>...) {
95 bool found{};
96 std::size_t index{std::numeric_limits<std::size_t>::max()};
97 auto handler = [&, counter = static_cast<std::size_t>(0)]<typename U>(std::type_identity<U>) mutable {
98 if (!found && Predicate(std::type_identity<U>{})) {
99 found = true;
100 index = counter;
101 }
102
103 counter++;
104 };
105
106 return (handler(std::type_identity<Ts>{}), ..., index);
107 });
108 };
109
110 template <type_list_like List, auto Predicate>
111 inline constexpr auto index_if_v = index_if<List, Predicate>::value;
112
113 template <type_list_like List, auto Predicate>
114 struct at_if {
115 using type = at_t<List, index_if_v<List, Predicate>>;
116 };
117
118 template <type_list_like List, auto Predicate>
119 using at_if_t = typename at_if<List, Predicate>::type;
120} // namespace essence
Definition type_list.hpp:47
Definition type_list.hpp:72
Definition type_list.hpp:114
Definition type_list.hpp:61
Definition type_list.hpp:93
Definition type_list.hpp:38
Definition type_list.hpp:50
Definition type_list.hpp:33