BioC++ core-0.7.0
The Modern C++ libraries for Bioinformatics.
 
Loading...
Searching...
No Matches
traits.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2022 deCODE Genetics
3// Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
4// Copyright (c) 2016-2021, Knut Reinert & MPI für molekulare Genetik
5// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
6// shipped with this file and also available at: https://github.com/biocpp/biocpp-core/blob/main/LICENSE.md
7// -----------------------------------------------------------------------------------------------------
8
14#pragma once
15
16#include <type_traits>
17
20
21// ----------------------------------------------------------------------------
22// bio::meta::list_traits::detail
23// ----------------------------------------------------------------------------
24
25namespace bio::meta::list_traits::detail
26{
27
33template <ptrdiff_t idx, typename... pack_t>
34std::type_identity<meta::detail::pack_traits::at<idx, pack_t...>> at(type_list<pack_t...>);
35
40template <typename... pack_t>
41std::type_identity<meta::detail::pack_traits::front<pack_t...>> front(type_list<pack_t...>);
42
47template <typename... pack_t>
48std::type_identity<meta::detail::pack_traits::back<pack_t...>> back(type_list<pack_t...>);
49
55template <typename... pack1_t, typename... pack2_t>
56type_list<pack1_t..., pack2_t...> concat(type_list<pack1_t...>, type_list<pack2_t...>);
57
64template <typename... pack1_t, typename... pack2_t, typename... more_lists_t>
65auto concat(type_list<pack1_t...>, type_list<pack2_t...>, more_lists_t...)
66{
67 return concat(type_list<pack1_t..., pack2_t...>{}, more_lists_t{}...);
68}
69
74template <typename... pack_t>
75meta::detail::pack_traits::drop_front<pack_t...> drop_front(type_list<pack_t...>);
76
82template <template <typename> typename trait_t, typename... pack_t>
83meta::detail::pack_traits::transform<trait_t, pack_t...> transform(type_list<pack_t...>);
84
90template <ptrdiff_t idx, typename... pack1_t>
91meta::detail::pack_traits::split_after<idx, pack1_t...> split_after(type_list<pack1_t...>);
92
98template <size_t count, typename t>
99auto repeat()
100{
101 if constexpr (count == 0)
102 return type_list<>{};
103 else if constexpr (count == 1)
104 return type_list<t>{};
105 else if constexpr (count == 2)
106 return type_list<t, t>{};
107 else if constexpr (count == 3)
108 return type_list<t, t, t>{};
109 else if constexpr (count == 4)
110 return type_list<t, t, t, t>{};
111 else if constexpr (count == 5)
112 return type_list<t, t, t, t, t>{};
113 else
114 return concat(repeat<5, t>(), repeat<count - 5, t>());
115}
116
123template <typename replace_t, ptrdiff_t idx, typename... pack_t>
124meta::detail::pack_traits::replace_at<replace_t, idx, pack_t...> replace_at(type_list<pack_t...>);
125
127inline constexpr type_list<> reverse(type_list<>)
128{
129 return {};
130}
131
133template <typename head_t, typename... pack_t>
134auto reverse(type_list<head_t, pack_t...>)
135{
136 return concat(reverse(type_list<pack_t...>{}), type_list<head_t>{});
137}
138
140template <typename... current_list_t>
141constexpr type_list<current_list_t...> type_list_difference(type_list<current_list_t...>, type_list<>)
142{
143 return {};
144}
145
147template <typename... current_list_t, typename remove_t, typename... remove_list_t>
148constexpr auto type_list_difference(meta::type_list<current_list_t...>, meta::type_list<remove_t, remove_list_t...>)
149{
150 constexpr auto pos = meta::detail::pack_traits::find<remove_t, current_list_t...>;
151 if constexpr (pos >= 0)
152 {
153 using split_list_t = meta::detail::pack_traits::split_after<pos, current_list_t...>;
154
155 using split_list1_t = typename split_list_t::first_type;
156 using split_list2_t = decltype(drop_front(typename split_list_t::second_type{}));
157 using filtered_list_t = decltype(concat(split_list1_t{}, split_list2_t{}));
158 return type_list_difference(filtered_list_t{}, meta::type_list<remove_t, remove_list_t...>{});
159 }
160 else
161 {
162 // remove_t not contained in current_list_t
163 using filtered_list_t = meta::type_list<current_list_t...>;
164 return type_list_difference(filtered_list_t{}, meta::type_list<remove_list_t...>{});
165 }
166}
167
168} // namespace bio::meta::list_traits::detail
169
170// ----------------------------------------------------------------------------
171// bio::meta::list_traits
172// ----------------------------------------------------------------------------
173
176{
177
183template <typename list_t>
184 requires template_specialisation_of<list_t, meta::type_list>
185inline constexpr size_t size = 0;
187
199template <typename... pack_t>
200inline constexpr size_t size<type_list<pack_t...>> = sizeof...(pack_t);
201
203template <typename query_t, typename list_t>
204 requires template_specialisation_of<list_t, meta::type_list>
205inline constexpr ptrdiff_t count = -1;
207
219template <typename query_t, typename... pack_t>
220inline constexpr ptrdiff_t count<query_t, type_list<pack_t...>> = meta::detail::pack_traits::count<query_t, pack_t...>;
221
223template <typename query_t, typename list_t>
224 requires template_specialisation_of<list_t, meta::type_list>
225inline constexpr ptrdiff_t find = -1;
227
239template <typename query_t, typename... pack_t>
240inline constexpr ptrdiff_t find<query_t, type_list<pack_t...>> =
241 meta::detail::pack_traits::detail::find<query_t, pack_t...>();
242
244template <template <typename> typename pred_t, typename list_t>
245 requires template_specialisation_of<list_t, meta::type_list>
246inline constexpr ptrdiff_t find_if = -1;
248
265template <template <typename> typename pred_t, typename... pack_t>
266inline constexpr ptrdiff_t find_if<pred_t, type_list<pack_t...>> =
267 meta::detail::pack_traits::detail::find_if<pred_t, pack_t...>();
268
280template <typename query_t, typename list_t>
281 requires template_specialisation_of<list_t, meta::type_list>
282inline constexpr bool contains = (find<query_t, list_t> != -1);
283
285
306template <ptrdiff_t idx, typename list_t>
307 requires((template_specialisation_of<list_t, meta::type_list>) &&
308 ((idx >= 0 && idx < size<list_t>) || (-idx <= size<list_t>)))
309using at = typename decltype(detail::at<idx>(list_t{}))::type;
310
324template <typename list_t>
325 requires((template_specialisation_of<list_t, meta::type_list>) && (size<list_t> > 0))
326using front = typename decltype(detail::front(list_t{}))::type;
327
344template <typename list_t>
345 requires((template_specialisation_of<list_t, meta::type_list>) && (size<list_t> > 0))
346using back = typename decltype(detail::back(list_t{}))::type;
347
349
370template <typename... lists_t>
371 requires((template_specialisation_of<lists_t, meta::type_list> && ...))
372using concat = decltype(detail::concat(lists_t{}...));
373
387template <typename list_t>
388 requires((template_specialisation_of<list_t, meta::type_list>) && (size<list_t> > 0))
389using drop_front = decltype(detail::drop_front(list_t{}));
390
405template <ptrdiff_t i, typename list_t>
406 requires((template_specialisation_of<list_t, meta::type_list>) && (i >= 0 && i <= size<list_t>))
407using take = typename decltype(detail::split_after<i>(list_t{}))::first_type;
408
423template <ptrdiff_t i, typename list_t>
424 requires((template_specialisation_of<list_t, meta::type_list>) && (i >= 0 && i <= size<list_t>))
425using drop = typename decltype(detail::split_after<i>(list_t{}))::second_type;
426
441template <ptrdiff_t i, typename list_t>
442 requires((template_specialisation_of<list_t, meta::type_list>) && (i >= 0 && i <= size<list_t>))
443using take_last = drop<size<list_t> - i, list_t>;
444
459template <ptrdiff_t i, typename list_t>
460 requires((template_specialisation_of<list_t, meta::type_list>) && (i >= 0 && i <= size<list_t>))
461using drop_last = take<size<list_t> - i, list_t>;
462
477template <ptrdiff_t i, typename list_t>
478 requires((template_specialisation_of<list_t, meta::type_list>) && (i >= 0 && i <= size<list_t>))
479using split_after = decltype(detail::split_after<i>(list_t{}));
480
498template <template <typename> typename trait_t, typename list_t>
499 requires template_specialisation_of<list_t, meta::type_list>
500using transform = decltype(detail::transform<trait_t>(list_t{}));
501
517template <typename replace_t, std::ptrdiff_t i, typename list_t>
518 requires((template_specialisation_of<list_t, meta::type_list>) && (i >= 0 && i < size<list_t>))
519using replace_at = decltype(detail::replace_at<replace_t, i>(list_t{}));
520
533template <size_t count, typename t>
534using repeat = decltype(detail::repeat<count, t>());
536
537} // namespace bio::meta::list_traits
constexpr auto size
A type trait that holds the size of a (semi-)alphabet.
Definition: concept.hpp:517
decltype(detail::repeat< count, t >()) repeat
Create a type list with the given type repeated count times..
Definition: traits.hpp:534
decltype(detail::concat(lists_t{}...)) concat
Join two meta::type_list s into one.
Definition: traits.hpp:372
typename decltype(detail::at< idx >(list_t{}))::type at
Return the type at given index from the type list.
Definition: traits.hpp:309
typename decltype(detail::front(list_t{}))::type front
Return the first type from the type list.
Definition: traits.hpp:326
decltype(detail::split_after< i >(list_t{})) split_after
Split a meta::type_list into two parts returned as a pair of meta::type_list.
Definition: traits.hpp:479
take< size< list_t > - i, list_t > drop_last
Return a meta::type_list of the types the input type list, except the last n.
Definition: traits.hpp:461
decltype(detail::drop_front(list_t{})) drop_front
Return a meta::type_list of all the types in the type list, except the first.
Definition: traits.hpp:389
constexpr bool contains
Whether a type occurs in a type list or not.
Definition: traits.hpp:282
decltype(detail::transform< trait_t >(list_t{})) transform
Apply a transformation trait to every type in the list and return a meta::type_list of the results.
Definition: traits.hpp:500
typename decltype(detail::split_after< i >(list_t{}))::first_type take
Return a meta::type_list of the first n types in the input type list.
Definition: traits.hpp:407
typename decltype(detail::split_after< i >(list_t{}))::second_type drop
Return a meta::type_list of the types in the input type list, except the first n.
Definition: traits.hpp:425
drop< size< list_t > - i, list_t > take_last
Return a meta::type_list of the last n types in the input type list.
Definition: traits.hpp:443
typename decltype(detail::back(list_t{}))::type back
Return the last type from the type list.
Definition: traits.hpp:346
decltype(detail::replace_at< replace_t, i >(list_t{})) replace_at
Replace the type at the given index with the given type.
Definition: traits.hpp:519
Namespace containing traits for working on bio::meta::type_list.
T reverse(T... args)
Type that contains multiple types.
Definition: type_list.hpp:30
Provides various traits for template packs.
Provides bio::meta::type_list.