SeqAn3  3.0.2
The Modern C++ library for sequence analysis.
traits.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2020, Knut Reinert & MPI für molekulare Genetik
4 // This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5 // shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
6 // -----------------------------------------------------------------------------------------------------
7 
13 #pragma once
14 
17 
18 // ----------------------------------------------------------------------------
19 // seqan3::pack_traits::detail
20 // ----------------------------------------------------------------------------
21 
22 namespace seqan3::pack_traits::detail
23 {
24 
31 template <typename query_t, typename ...pack_t>
32 constexpr ptrdiff_t find()
33 {
34  ptrdiff_t i = 0;
35  return ((SEQAN3_IS_SAME(query_t, pack_t) ? false : ++i) && ...) ? -1 : i;
36 }
37 
44 template <template <typename> typename pred_t, typename ...pack_t>
45 constexpr ptrdiff_t find_if()
46 {
47  ptrdiff_t i = 0;
48  return ((pred_t<pack_t>::value ? false : ++i) && ...) ? -1 : i;
49 }
50 
57 template <ptrdiff_t idx, typename head_t, typename ...tail_t>
58 auto at()
59 {
60  if constexpr (idx == 0)
61  return std::type_identity<head_t>{};
62  else if constexpr (idx > 0)
63 #ifdef __clang__
64  return std::type_identity<__type_pack_element<idx - 1, tail_t...>>{};
65 #else
66  return at<idx - 1, tail_t...>();
67 #endif // __clang__
68  else
69  return at<sizeof...(tail_t) + 1 + idx, head_t, tail_t...>();
70 }
71 
77 template <typename head_t, typename ...tail_t>
79 
85 template <typename head_t, typename ...tail_t>
86 type_list<tail_t...> drop_front();
87 
88 } // namespace seqan3::pack_traits::detail
89 
90 // ----------------------------------------------------------------------------
91 // seqan3::pack_traits
92 // ----------------------------------------------------------------------------
93 
94 namespace seqan3::pack_traits
95 {
96 
115 template <typename ...pack_t>
116 inline constexpr size_t size = sizeof...(pack_t);
117 
133 template <typename query_t, typename ...pack_t>
134 inline constexpr ptrdiff_t count = (SEQAN3_IS_SAME(query_t, pack_t) + ... + 0);
135 
151 template <typename query_t, typename ...pack_t>
152 inline constexpr ptrdiff_t find = seqan3::pack_traits::detail::find<query_t, pack_t...>();
153 
174 template <template <typename> typename pred_t, typename ...pack_t>
175 inline constexpr ptrdiff_t find_if = seqan3::pack_traits::detail::find_if<pred_t, pack_t...>();
176 
192 template <typename query_t, typename ...pack_t>
193 inline constexpr bool contains = (find<query_t, pack_t...> != -1);
195 
216 template <ptrdiff_t idx, typename ...pack_t>
218  requires (idx >= 0 && idx < sizeof...(pack_t)) ||
219  (-idx <= sizeof...(pack_t))
221 using at = typename decltype(detail::at<idx, pack_t...>())::type;
222 
236 template <typename ...pack_t>
238  requires (sizeof...(pack_t) > 0)
240 using front = typename decltype(detail::front<pack_t...>())::type;
241 
258 template <typename ...pack_t>
260  requires (sizeof...(pack_t) > 0)
262 using back = typename decltype((std::type_identity<pack_t>{}, ...))::type; // use comma operator
263 
265 
283 template <typename ...pack_t>
285  requires (sizeof...(pack_t) > 0)
287 using drop_front = typename decltype(detail::drop_front<pack_t...>())::type;
288 
306 template <template <typename> typename trait_t, typename ...pack_t>
307 using transform = seqan3::type_list<trait_t<pack_t>...>;
308 
310 
311 } // namespace seqan3::pack_traits
312 
313 // ----------------------------------------------------------------------------
314 // seqan3::list_traits
315 // ----------------------------------------------------------------------------
316 
317 namespace seqan3::list_traits::detail
318 {
319 
325 template <ptrdiff_t idx, typename ...pack_t>
327 
332 template <typename ...pack_t>
334 
339 template <typename ...pack_t>
341 
347 template <typename ...pack1_t,
348  typename ...pack2_t>
349 type_list<pack1_t..., pack2_t...> concat(type_list<pack1_t...>, type_list<pack2_t...>);
350 
357 template <typename ...pack1_t,
358  typename ...pack2_t,
359  typename ...more_lists_t>
360 auto concat(type_list<pack1_t...>, type_list<pack2_t...>, more_lists_t ...)
361 {
362  return concat(type_list<pack1_t..., pack2_t...>{}, more_lists_t{}...);
363 }
364 
369 template <typename ...pack_t>
371 
379 template <ptrdiff_t idx,
380  typename ...pack1_t,
381  typename head_t, typename ...pack2_t>
383 {
384  if constexpr (idx == sizeof...(pack2_t) + 1)
385  return std::pair<type_list<pack1_t..., head_t, pack2_t...>, type_list<>>{};
386  else if constexpr (idx == 0)
387  return std::pair<type_list<pack1_t...>, type_list<head_t, pack2_t...>>{};
388  else
389  return split_after<idx - 1>(type_list<pack1_t..., head_t>{}, type_list<pack2_t...>{});
390 }
391 
397 template <template <typename> typename trait_t, typename ...pack_t>
399 
407 template <typename replace_t,
408  typename ...pack1_t,
409  typename head_t, typename ...pack2_t>
410 type_list<pack1_t..., replace_t, pack2_t...>
412 
413 } // namespace seqan3::list_traits::detail
414 
415 // ----------------------------------------------------------------------------
416 // seqan3::list_traits
417 // ----------------------------------------------------------------------------
418 
419 //TODO think about whether the type_list_specialisation concept check is expensive and necessary
420 
422 namespace seqan3::list_traits
423 {
424 
429 template <seqan3::detail::type_list_specialisation list_t>
431 inline constexpr size_t size = 0;
433 
440 template <typename ...pack_t>
441 inline constexpr size_t size<type_list<pack_t...>> = sizeof...(pack_t);
442 
444 template <typename query_t, seqan3::detail::type_list_specialisation list_t>
445 inline constexpr ptrdiff_t count = -1;
447 
454 template <typename query_t, typename ...pack_t>
455 inline constexpr ptrdiff_t count<query_t, type_list<pack_t...>> =
456  seqan3::pack_traits::count<query_t, pack_t...>;
457 
459 template <typename query_t, seqan3::detail::type_list_specialisation list_t>
460 inline constexpr ptrdiff_t find = -1;
462 
469 template <typename query_t, typename ...pack_t>
470 inline constexpr ptrdiff_t find<query_t, type_list<pack_t...>> =
471  seqan3::pack_traits::detail::find<query_t, pack_t...>();
472 
474 template <template <typename> typename pred_t, seqan3::detail::type_list_specialisation list_t>
475 inline constexpr ptrdiff_t find_if = -1;
477 
484 template <template <typename> typename pred_t, typename ...pack_t>
485 inline constexpr ptrdiff_t find_if<pred_t, type_list<pack_t...>> =
486  seqan3::pack_traits::detail::find_if<pred_t, pack_t...>();
487 
494 template <typename query_t, seqan3::detail::type_list_specialisation list_t>
495 inline constexpr bool contains = (find<query_t, list_t> != -1);
496 
498 
519 template <ptrdiff_t idx, seqan3::detail::type_list_specialisation list_t>
521  requires (idx >= 0 && idx < size<list_t>) || (-idx <= size<list_t>)
523 using at = typename decltype(detail::at<idx>(list_t{}))::type;
524 
538 template <seqan3::detail::type_list_specialisation list_t>
540  requires (size<list_t> > 0)
542 using front = typename decltype(detail::front(list_t{}))::type;
543 
560 template <seqan3::detail::type_list_specialisation list_t>
562  requires (size<list_t> > 0)
564 using back = typename decltype(detail::back(list_t{}))::type;
565 
567 
588 template <typename ...lists_t>
590  requires (seqan3::detail::type_list_specialisation<lists_t> && ...)
592 using concat = decltype(detail::concat(lists_t{}...));
593 
607 template <seqan3::detail::type_list_specialisation list_t>
609  requires (size<list_t> > 0)
611 using drop_front = decltype(detail::drop_front(list_t{}));
612 
627 template <ptrdiff_t i, seqan3::detail::type_list_specialisation list_t>
629  requires (i >= 0 && i <= size<list_t>)
631 using take = typename decltype(detail::split_after<i>(type_list<>{}, list_t{}))::first_type;
632 
647 template <ptrdiff_t i, seqan3::detail::type_list_specialisation list_t>
649  requires (i >= 0 && i <= size<list_t>)
651 using drop = typename decltype(detail::split_after<i>(type_list<>{}, list_t{}))::second_type;
652 
667 template <ptrdiff_t i, seqan3::detail::type_list_specialisation list_t>
669  requires (i >= 0 && i <= size<list_t>)
671 using take_last = drop<size<list_t> - i, list_t>;
672 
687 template <ptrdiff_t i, seqan3::detail::type_list_specialisation list_t>
689  requires (i >= 0 && i <= size<list_t>)
691 using drop_last = take<size<list_t> - i, list_t>;
692 
707 template <ptrdiff_t i, seqan3::detail::type_list_specialisation list_t>
709  requires (i >= 0 && i <= size<list_t>)
711 using split_after = decltype(detail::split_after<i>(type_list<>{}, list_t{}));
712 
730 template <template <typename> typename trait_t, seqan3::detail::type_list_specialisation list_t>
731 using transform = decltype(detail::transform<trait_t>(list_t{}));
732 
748 template <typename replace_t, std::ptrdiff_t i, seqan3::detail::type_list_specialisation list_t>
750  requires (i >= 0 && i < size<list_t>)
752 using replace_at = decltype(detail::replace_at<replace_t>(detail::split_after<i>(type_list<>{}, list_t{})));
753 
755 
756 } // namespace seqan3::list_traits
757 
758 // ----------------------------------------------------------------------------
759 // seqan3::pack_traits that depend on list_traits
760 // ----------------------------------------------------------------------------
761 
762 namespace seqan3::pack_traits
763 {
764 
783 template <ptrdiff_t i, typename ...pack_t>
785  requires (i >= 0 && i <= sizeof...(pack_t))
787 using take = seqan3::list_traits::take<i, type_list<pack_t...>>;
788 
803 template <ptrdiff_t i, typename ...pack_t>
805  requires (i >= 0 && i <= sizeof...(pack_t))
807 using drop = seqan3::list_traits::drop<i, type_list<pack_t...>>;
808 
823 template <ptrdiff_t i, typename ...pack_t>
825  requires (i >= 0 && i <= sizeof...(pack_t))
827 using take_last = seqan3::list_traits::take_last<i, type_list<pack_t...>>;
828 
843 template <ptrdiff_t i, typename ...pack_t>
845  requires (i >= 0 && i <= sizeof...(pack_t))
847 using drop_last = seqan3::list_traits::drop_last<i, type_list<pack_t...>>;
848 
863 template <ptrdiff_t i, typename ...pack_t>
865  requires (i >= 0 && i <= sizeof...(pack_t))
867 using split_after = seqan3::list_traits::split_after<i, type_list<pack_t...>>;
868 
884 template <typename replace_t, std::ptrdiff_t i, typename ...pack_t>
886  requires (i >= 0 && i < sizeof...(pack_t))
888 using replace_at = decltype(seqan3::list_traits::replace_at<replace_t, i, type_list<pack_t...>>());
889 
891 
892 } // namespace seqan3::pack_traits
seqan3::list_traits::transform
decltype(detail::transform< trait_t >(list_t{})) transform
Apply a transformation trait to every type in the list and return a seqan3::type_list of the results.
Definition: traits.hpp:731
seqan3::pack_traits::replace_at
decltype(seqan3::list_traits::replace_at< replace_t, i, type_list< pack_t... > >()) replace_at
Replace the type at the given index with the given type.
Definition: traits.hpp:888
seqan3::pack_traits::take_last
seqan3::list_traits::take_last< i, type_list< pack_t... > > take_last
Return a seqan3::type_list of the last n types in the type pack.
Definition: traits.hpp:827
seqan3::pack_traits::split_after
seqan3::list_traits::split_after< i, type_list< pack_t... > > split_after
Split a type pack into two parts returned as a pair of seqan3::type_list.
Definition: traits.hpp:867
seqan3::list_traits::replace_at
decltype(detail::replace_at< replace_t >(detail::split_after< i >(type_list<>{}, list_t{}))) replace_at
Replace the type at the given index with the given type.
Definition: traits.hpp:752
seqan3::type_list
meta::list< types... > type_list
Type that contains multiple types, an alias for meta::list.
Definition: type_list.hpp:31
std::pair
seqan3::pack_traits::find
constexpr ptrdiff_t find
Get the index of the first occurrence of a type in a pack.
Definition: traits.hpp:152
basic.hpp
Provides various type traits on generic types.
seqan3::list_traits::back
typename decltype(detail::back(list_t{}))::type back
Return the last type from the type list.
Definition: traits.hpp:564
seqan3::list_traits::drop_front
decltype(detail::drop_front(list_t{})) drop_front
Return a seqan3::type_list of all the types in the type list, except the first.
Definition: traits.hpp:611
seqan3::list_traits::take
typename decltype(detail::split_after< i >(type_list<>{}, list_t{}))::first_type take
Return a seqan3::type_list of the first n types in the input type list.
Definition: traits.hpp:631
seqan3::list_traits::split_after
decltype(detail::split_after< i >(type_list<>{}, list_t{})) split_after
Split a seqan3::type_list into two parts returned as a pair of seqan3::type_list.
Definition: traits.hpp:711
seqan3::list_traits
Namespace containing traits for working on seqan3::type_list.
seqan3::list_traits::drop_last
take< size< list_t > - i, list_t > drop_last
Return a seqan3::type_list of the types the input type list, except the last n.
Definition: traits.hpp:691
seqan3::pack_traits::contains
constexpr bool contains
Whether a type occurs in a pack or not.
Definition: traits.hpp:193
SEQAN3_IS_SAME
#define SEQAN3_IS_SAME(...)
A macro that behaves like std::is_same_v, except that it doesn't need to instantiate the template on ...
Definition: basic.hpp:168
seqan3::list_traits::drop
typename decltype(detail::split_after< i >(type_list<>{}, list_t{}))::second_type drop
Return a seqan3::type_list of the types in the input type list, except the first n.
Definition: traits.hpp:651
seqan3::list_traits::take_last
drop< size< list_t > - i, list_t > take_last
Return a seqan3::type_list of the last n types in the input type list.
Definition: traits.hpp:671
seqan3::pack_traits::drop_front
typename decltype(detail::drop_front< pack_t... >())::type drop_front
Return a seqan3::type_list of all the types in the type pack, except the first.
Definition: traits.hpp:287
seqan3
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
seqan3::pack_traits::find_if
constexpr ptrdiff_t find_if
Get the index of the first type in a pack that satisfies the given predicate.
Definition: traits.hpp:175
seqan3::list_traits::front
typename decltype(detail::front(list_t{}))::type front
Return the first type from the type list.
Definition: traits.hpp:542
seqan3::pack_traits::drop_last
seqan3::list_traits::drop_last< i, type_list< pack_t... > > drop_last
Return a seqan3::type_list of the types the type pack, except the last n.
Definition: traits.hpp:847
seqan3::list_traits::at
typename decltype(detail::at< idx >(list_t{}))::type at
Return the type at given index from the type list.
Definition: traits.hpp:523
seqan3::pack_traits::front
typename decltype(detail::front< pack_t... >())::type front
Return the first type from the type pack.
Definition: traits.hpp:240
seqan3::pack_traits::drop
seqan3::list_traits::drop< i, type_list< pack_t... > > drop
Return a seqan3::type_list of the types in the type pack, except the first n.
Definition: traits.hpp:807
seqan3::pack_traits::size
constexpr size_t size
The size of a type pack.
Definition: traits.hpp:116
seqan3::pack_traits::back
typename decltype((std::type_identity< pack_t >{},...))::type back
Return the last type from the type pack.
Definition: traits.hpp:262
std::type_identity
The identity transformation (a transformation_trait that returns the input).
std
SeqAn specific customisations in the standard namespace.
seqan3::pack_traits::take
seqan3::list_traits::take< i, type_list< pack_t... > > take
Return a seqan3::type_list of the first n types in the type pack.
Definition: traits.hpp:787
seqan3::list_traits::concat
decltype(detail::concat(lists_t{}...)) concat
Join two seqan3::type_list s into one.
Definition: traits.hpp:592
seqan3::pack_traits::transform
seqan3::type_list< trait_t< pack_t >... > transform
Apply a transformation trait to every type in the pack and return a seqan3::type_list of the results.
Definition: traits.hpp:307
seqan3::pack_traits::at
typename decltype(detail::at< idx, pack_t... >())::type at
Return the type at given index from the type pack.
Definition: traits.hpp:221
seqan3::pack_traits
Namespace containing traits for working on type packs.
seqan3::pack_traits::count
constexpr ptrdiff_t count
Count the occurrences of a type in a pack.
Definition: traits.hpp:134
type_list.hpp
Provides seqan3::type_list.