SeqAn3  3.2.0
The Modern C++ library for sequence analysis.
alphabet_tuple_base.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2022, 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 
15 #include <cassert>
16 #include <concepts>
17 #include <utility>
18 
30 
31 namespace seqan3::detail
32 {
33 
35 template <typename tuple_derived_t, typename rhs_t, typename... component_types>
36 inline constexpr bool tuple_general_guard =
37  (!std::same_as<rhs_t, tuple_derived_t>)&&(!std::same_as<rhs_t, alphabet_tuple_base<component_types...>>)&&(
38  !std::is_base_of_v<tuple_derived_t, rhs_t>)&&(!(std::same_as<rhs_t, component_types> || ...))
39  && (!list_traits::contains<tuple_derived_t, recursive_required_types_t<rhs_t>>);
40 
42 template <typename lhs_t, typename tuple_derived_t, typename rhs_t, typename... component_types>
43 inline constexpr bool tuple_eq_guard =
44  (instantiate_if_v<lazy<weakly_equality_comparable_with_trait, rhs_t, component_types>,
45  std::same_as<lhs_t, tuple_derived_t>
46  && tuple_general_guard<tuple_derived_t, rhs_t, component_types...>>
47  || ...);
48 
50 template <typename lhs_t, typename tuple_derived_t, typename rhs_t, typename... component_types>
51 inline constexpr bool tuple_order_guard =
52  (instantiate_if_v<lazy<weakly_ordered_with_trait, rhs_t, component_types>,
53  std::same_as<lhs_t, tuple_derived_t>
54  && tuple_general_guard<lhs_t, tuple_derived_t, rhs_t, component_types...>>
55  || ...);
56 
57 } // namespace seqan3::detail
58 
59 namespace seqan3
60 {
61 
62 // forwards
64 template <typename t>
65 decltype(auto) get();
66 
67 template <size_t i>
68 decltype(auto) get();
70 
110 template <typename derived_type, typename... component_types>
111  requires (detail::writable_constexpr_semialphabet<component_types> && ...) && (std::regular<component_types> && ...)
112 class alphabet_tuple_base :
113  public alphabet_base<derived_type,
114  (1 * ... * alphabet_size<component_types>),
115  void> // no char type, because this is only semi_alphabet
116 {
117 private:
119  using base_t = alphabet_base<derived_type,
120  (1 * ... * alphabet_size<component_types>),
121  void>; // no char type, because this is only semi_alphabet
122 
124  using component_list = seqan3::type_list<component_types...>;
125 
127  template <typename type>
128  static constexpr bool is_component = seqan3::list_traits::contains<type, component_list>;
129 
131  template <typename type>
132  static constexpr bool is_unique_component = (seqan3::list_traits::count<type, component_list> == 1);
133 
134  // forward declaration: see implementation below
135  template <typename alphabet_type, size_t index>
136  class component_proxy;
137 
141  constexpr alphabet_tuple_base() noexcept : base_t{}
142  {}
143  constexpr alphabet_tuple_base(alphabet_tuple_base const &) = default;
144  constexpr alphabet_tuple_base(alphabet_tuple_base &&) = default;
145  constexpr alphabet_tuple_base & operator=(alphabet_tuple_base const &) = default;
146  constexpr alphabet_tuple_base & operator=(alphabet_tuple_base &&) = default;
147  ~alphabet_tuple_base() = default;
148 
149  using base_t::base_t;
151 
154  friend derived_type;
155 
156  // Import from base:
157  using typename base_t::rank_type;
158 
159 public:
160  // Import from base:
161  using base_t::alphabet_size;
162  using base_t::assign_rank;
163  using base_t::to_rank;
164 
167  using seqan3_required_types = component_list;
170  using seqan3_recursive_required_types = list_traits::concat<
171  component_list,
172  detail::transformation_trait_or_t<detail::recursive_required_types<component_types>, seqan3::type_list<>>...>;
175  static constexpr bool seqan3_alphabet_tuple_like = true;
176 
185  constexpr alphabet_tuple_base(component_types... components) noexcept
186  {
187  assign_rank(rank_sum_helper(components..., std::make_index_sequence<sizeof...(component_types)>{}));
188  }
189 
200  template <typename component_type>
201  requires (!std::is_base_of_v<alphabet_tuple_base, component_type>) && is_unique_component<component_type>
202  constexpr explicit alphabet_tuple_base(component_type const alph) noexcept : alphabet_tuple_base{}
203  {
204  get<component_type>(*this) = alph;
205  }
206 
222  template <typename indirect_component_type>
223  requires ((detail::instantiate_if_v<
224  detail::lazy<std::is_convertible, indirect_component_type, component_types>,
225  detail::tuple_general_guard<derived_type, indirect_component_type, component_types...>>
226  || ...))
227  constexpr explicit alphabet_tuple_base(indirect_component_type const alph) noexcept : alphabet_tuple_base{}
228  {
229  using component_predicate = detail::implicitly_convertible_from<indirect_component_type>;
230  constexpr auto component_position =
231  seqan3::list_traits::find_if<component_predicate::template invoke, component_list>;
232  using component_type = seqan3::list_traits::at<component_position, component_list>;
233  component_type tmp(alph); // delegate construction
234  get<component_type>(*this) = tmp;
235  }
236 
238  template <typename indirect_component_type>
239  requires ((!(detail::instantiate_if_v<
240  detail::lazy<std::is_convertible, indirect_component_type, component_types>,
241  detail::tuple_general_guard<derived_type, indirect_component_type, component_types...>>
242  || ...))
243  && (detail::instantiate_if_v<
244  detail::lazy<std::is_constructible, component_types, indirect_component_type>,
245  detail::tuple_general_guard<derived_type, indirect_component_type, component_types...>>
246  || ...))
247  constexpr explicit alphabet_tuple_base(indirect_component_type const alph) noexcept : alphabet_tuple_base{}
248  {
249  using component_predicate = detail::constructible_from<indirect_component_type>;
250  constexpr auto component_position =
251  seqan3::list_traits::find_if<component_predicate::template invoke, component_list>;
252  using component_type = seqan3::list_traits::at<component_position, component_list>;
253  component_type tmp(alph); // delegate construction
254  get<component_type>(*this) = tmp;
255  }
257 
268  template <typename component_type>
269  requires (!std::derived_from<component_type, alphabet_tuple_base>) && is_unique_component<component_type>
270  constexpr derived_type & operator=(component_type const alph) noexcept
271  {
272  get<component_type>(*this) = alph;
273  return static_cast<derived_type &>(*this);
274  }
275 
287  template <typename indirect_component_type>
288  requires ((!std::derived_from<indirect_component_type, alphabet_tuple_base>)
289  && (!is_unique_component<indirect_component_type>)
290  && (std::assignable_from<component_types, indirect_component_type> || ...))
291  constexpr derived_type & operator=(indirect_component_type const alph) noexcept
292  {
293  using component_predicate = detail::assignable_from<indirect_component_type>;
294  constexpr auto component_position =
295  seqan3::list_traits::find_if<component_predicate::template invoke, component_list>;
296  using component_type = seqan3::list_traits::at<component_position, component_list>;
297  get<component_type>(*this) = alph; // delegate assignment
298  return static_cast<derived_type &>(*this);
299  }
301  // If not assignable but implicit convertible, convert first and assign afterwards
302  template <typename indirect_component_type>
303  requires ((!std::derived_from<indirect_component_type, alphabet_tuple_base>)
304  && (!is_unique_component<indirect_component_type>)
305  && (!(std::assignable_from<component_types, indirect_component_type> || ...))
306  && (std::convertible_to<indirect_component_type, component_types> || ...))
307  constexpr derived_type & operator=(indirect_component_type const alph) noexcept
308  {
309  using component_predicate = detail::implicitly_convertible_from<indirect_component_type>;
310  constexpr auto component_position =
311  seqan3::list_traits::find_if<component_predicate::template invoke, component_list>;
312  using component_type = seqan3::list_traits::at<component_position, component_list>;
313  component_type tmp(alph);
314  get<component_type>(*this) = tmp;
315  return static_cast<derived_type &>(*this);
316  }
317 
318  template <typename indirect_component_type>
319  requires ((!std::derived_from<indirect_component_type, alphabet_tuple_base>)
320  && (!is_unique_component<indirect_component_type>)
321  && (!(std::assignable_from<component_types, indirect_component_type> || ...))
322  && (!(std::convertible_to<indirect_component_type, component_types> || ...))
323  && (std::constructible_from<component_types, indirect_component_type> || ...))
324  constexpr derived_type & operator=(indirect_component_type const alph) noexcept
325  {
326  using component_predicate = detail::constructible_from<indirect_component_type>;
327  constexpr auto component_position =
328  seqan3::list_traits::find_if<component_predicate::template invoke, component_list>;
329  using component_type = seqan3::list_traits::at<component_position, component_list>;
330  component_type tmp(alph); // delegate construction
331  get<component_type>(*this) = tmp;
332  return static_cast<derived_type &>(*this);
333  }
336 
347  template <size_t index>
348  friend constexpr auto get(alphabet_tuple_base & l) noexcept
349  {
350  static_assert(index < sizeof...(component_types), "Index out of range.");
351 
352  using t = seqan3::list_traits::at<index, component_list>;
353  t val{};
354 
355  seqan3::assign_rank_to(l.to_component_rank<index>(), val);
356 
357  return component_proxy<t, index>{val, l};
358  }
359 
366  template <typename type>
367  friend constexpr auto get(alphabet_tuple_base & l) noexcept
368  requires is_unique_component<type>
369  {
370  return get<seqan3::list_traits::find<type, component_list>>(l);
371  }
372 
379  template <size_t index>
380  friend constexpr auto get(alphabet_tuple_base const & l) noexcept
381  {
382  static_assert(index < sizeof...(component_types), "Index out of range.");
383 
384  using t = seqan3::list_traits::at<index, component_list>;
385 
386  return seqan3::assign_rank_to(l.to_component_rank<index>(), t{});
387  }
388 
395  template <typename type>
396  friend constexpr type get(alphabet_tuple_base const & l) noexcept
397  requires is_unique_component<type>
398  {
399  return get<seqan3::list_traits::find<type, component_list>>(l);
400  }
401 
406  template <typename type>
407  constexpr operator type() const noexcept
408  requires is_unique_component<type>
409  {
410  return get<type>(*this);
411  }
413 
431  template <typename derived_type_t, typename indirect_component_type>
432  friend constexpr auto operator==(derived_type_t const lhs, indirect_component_type const rhs) noexcept
433  -> std::enable_if_t<
434  detail::tuple_eq_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
435  bool>
436  {
437  using component_predicate = detail::weakly_equality_comparable_with_<indirect_component_type>;
438  constexpr auto component_position =
439  seqan3::list_traits::find_if<component_predicate::template invoke, component_list>;
440  using component_type = seqan3::list_traits::at<component_position, component_list>;
441  return get<component_type>(lhs) == rhs;
442  }
443 
445  template <typename derived_type_t, typename indirect_component_type>
446  friend constexpr auto operator==(indirect_component_type const lhs, derived_type_t const rhs) noexcept
447  -> std::enable_if_t<
448  detail::tuple_eq_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
449  bool>
450  {
451  return rhs == lhs;
452  }
453 
455  template <typename derived_type_t, typename indirect_component_type>
456  friend constexpr auto operator!=(derived_type_t const lhs, indirect_component_type const rhs) noexcept
457  -> std::enable_if_t<
458  detail::tuple_eq_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
459  bool>
460  {
461  using component_predicate = detail::weakly_equality_comparable_with_<indirect_component_type>;
462  constexpr auto component_position =
463  seqan3::list_traits::find_if<component_predicate::template invoke, component_list>;
464  using component_type = seqan3::list_traits::at<component_position, component_list>;
465  return get<component_type>(lhs) != rhs;
466  }
467 
469  template <typename derived_type_t, typename indirect_component_type>
470  friend constexpr auto operator!=(indirect_component_type const lhs, derived_type_t const rhs) noexcept
471  -> std::enable_if_t<
472  detail::tuple_eq_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
473  bool>
474  {
475  return rhs != lhs;
476  }
477 
479  template <typename derived_type_t, typename indirect_component_type>
480  friend constexpr auto operator<(derived_type_t const lhs, indirect_component_type const rhs) noexcept
481  -> std::enable_if_t<
482  detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
483  bool>
484  {
485  using component_predicate = detail::weakly_ordered_with_<indirect_component_type>;
486  constexpr auto component_position =
487  seqan3::list_traits::find_if<component_predicate::template invoke, component_list>;
488  using component_type = seqan3::list_traits::at<component_position, component_list>;
489  return get<component_type>(lhs) < rhs;
490  }
491 
493  template <typename derived_type_t, typename indirect_component_type>
494  friend constexpr auto operator<(indirect_component_type const lhs, derived_type_t const rhs) noexcept
495  -> std::enable_if_t<
496  detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
497  bool>
498  {
499  return rhs > lhs;
500  }
501 
503  template <typename derived_type_t, typename indirect_component_type>
504  friend constexpr auto operator<=(derived_type_t const lhs, indirect_component_type const rhs) noexcept
505  -> std::enable_if_t<
506  detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
507  bool>
508  {
509  using component_predicate = detail::weakly_ordered_with_<indirect_component_type>;
510  constexpr auto component_position =
511  seqan3::list_traits::find_if<component_predicate::template invoke, component_list>;
512  using component_type = seqan3::list_traits::at<component_position, component_list>;
513  return get<component_type>(lhs) <= rhs;
514  }
515 
517  template <typename derived_type_t, typename indirect_component_type>
518  friend constexpr auto operator<=(indirect_component_type const lhs, derived_type_t const rhs) noexcept
519  -> std::enable_if_t<
520  detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
521  bool>
522  {
523  return rhs >= lhs;
524  }
525 
527  template <typename derived_type_t, typename indirect_component_type>
528  friend constexpr auto operator>(derived_type_t const lhs, indirect_component_type const rhs) noexcept
529  -> std::enable_if_t<
530  detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
531  bool>
532  {
533  using component_predicate = detail::weakly_ordered_with_<indirect_component_type>;
534  constexpr auto component_position =
535  seqan3::list_traits::find_if<component_predicate::template invoke, component_list>;
536  using component_type = seqan3::list_traits::at<component_position, component_list>;
537  return get<component_type>(lhs) > rhs;
538  }
539 
541  template <typename derived_type_t, typename indirect_component_type>
542  friend constexpr auto operator>(indirect_component_type const lhs, derived_type_t const rhs) noexcept
543  -> std::enable_if_t<
544  detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
545  bool>
546  {
547  return rhs < lhs;
548  }
549 
551  template <typename derived_type_t, typename indirect_component_type>
552  friend constexpr auto operator>=(derived_type_t const lhs, indirect_component_type const rhs) noexcept
553  -> std::enable_if_t<
554  detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
555  bool>
556  {
557  using component_predicate = detail::weakly_ordered_with_<indirect_component_type>;
558  constexpr auto component_position =
559  seqan3::list_traits::find_if<component_predicate::template invoke, component_list>;
560  using component_type = seqan3::list_traits::at<component_position, component_list>;
561  return get<component_type>(lhs) >= rhs;
562  }
563 
565  template <typename derived_type_t, typename indirect_component_type>
566  friend constexpr auto operator>=(indirect_component_type const lhs, derived_type_t const rhs) noexcept
567  -> std::enable_if_t<
568  detail::tuple_order_guard<derived_type_t, derived_type, indirect_component_type, component_types...>,
569  bool>
570  {
571  return rhs <= lhs;
572  }
574 
575 private:
577  template <size_t index>
578  constexpr rank_type to_component_rank() const noexcept
579  {
580  if constexpr (alphabet_size < 1024) // computation is cached for small alphabets
581  {
582  return rank_to_component_rank[index][to_rank()];
583  }
584  else
585  {
586  return (to_rank() / cummulative_alph_sizes[index])
587  % seqan3::alphabet_size<pack_traits::at<index, component_types...>>;
588  }
589  }
590 
592  template <size_t index>
593  constexpr void assign_component_rank(ptrdiff_t const r) noexcept
594  {
595  assign_rank(static_cast<ptrdiff_t>(to_rank())
596  + ((r - static_cast<ptrdiff_t>(to_component_rank<index>()))
597  * static_cast<ptrdiff_t>(cummulative_alph_sizes[index])));
598  }
599 
601  static constexpr std::array<rank_type, component_list::size()> cummulative_alph_sizes{
602  []() constexpr {// create array (1, |sigma1|, |sigma1|*|sigma2|, ... , |sigma1|*...*|sigmaN|)
603  std::array<rank_type, component_list::size() + 1> ret{};
604  ret[0] = 1;
605  size_t count = 1;
606  using reverse_list_t = decltype(seqan3::list_traits::detail::reverse(component_list{}));
607  seqan3::detail::for_each<reverse_list_t>([&](auto alphabet_type_identity) constexpr {
608  using alphabet_t = typename decltype(alphabet_type_identity)::type;
609  ret[count] = static_cast<rank_type>(seqan3::alphabet_size<alphabet_t> * ret[count - 1]);
610  ++count;
611  });
612 
613  // reverse and strip one: (|sigma1|*...*|sigmaN-1|, ... |sigma1|*|sigma2|, |sigma1|, 1)
614  // reverse order guarantees that the first alphabet is the most significant rank contributer
615  // resulting in element-wise alphabetical ordering on comparison
616  std::array<rank_type, component_list::size()> ret2{};
617  for (size_t i = 0; i < component_list::size(); ++i)
618  ret2[i] = ret[component_list::size() - i - 1];
619 
620  return ret2;
621 }()
622 }; // namespace seqan3
623 
625 template <std::size_t... idx>
626 static constexpr rank_type rank_sum_helper(component_types... components, std::index_sequence<idx...> const &) noexcept
627 {
628  return ((seqan3::to_rank(components) * cummulative_alph_sizes[idx]) + ...);
629 }
630 
632 static constexpr std::array < std::array<rank_type,
633  alphabet_size<1024 ? alphabet_size : 0>, // not for big alphs
634  list_traits::size<component_list>>
635  rank_to_component_rank{
636  []() constexpr {std::array < std::array<rank_type,
637  alphabet_size<1024 ? alphabet_size : 0>, // not for big alphs
638  list_traits::size<component_list>> ret{};
639 
640 if constexpr (alphabet_size < 1024)
641 {
642  std::array<size_t, alphabet_size> alph_sizes{seqan3::alphabet_size<component_types>...};
643 
644  for (size_t i = 0; i < list_traits::size<component_list>; ++i)
645  for (size_t j = 0; j < static_cast<size_t>(alphabet_size); ++j)
646  ret[i][j] = (j / cummulative_alph_sizes[i]) % alph_sizes[i];
647 }
648 
649 return ret;
650 }
651 ()
652 }
653 ;
654 }
655 ;
656 
663 template <typename derived_type, typename... component_types>
664  requires (detail::writable_constexpr_semialphabet<component_types> && ...) && (std::regular<component_types> && ...)
665 template <typename alphabet_type, size_t index>
666 class alphabet_tuple_base<derived_type, component_types...>::component_proxy :
667  public alphabet_proxy<component_proxy<alphabet_type, index>, alphabet_type>
668 {
669 private:
671  using base_t = alphabet_proxy<component_proxy<alphabet_type, index>, alphabet_type>;
673  friend base_t;
674 
676  alphabet_tuple_base * parent;
677 
679  constexpr void on_update() noexcept
680  {
681  parent->assign_component_rank<index>(this->to_rank());
682  }
683 
684 public:
685  //Import from base type:
686  using base_t::operator=;
687 
692  component_proxy() = delete;
693  constexpr component_proxy(component_proxy const &) = default;
694  constexpr component_proxy(component_proxy &&) = default;
695  constexpr component_proxy & operator=(component_proxy const &) = default;
696  constexpr component_proxy & operator=(component_proxy &&) = default;
697  ~component_proxy() = default;
698 
700  constexpr component_proxy(alphabet_type const l, alphabet_tuple_base & p) : base_t{l}, parent{&p}
701  {}
702 
703  // Does not inherit the base's constructor for alphabet_type so as not to cause ambiguity
705 
715  friend constexpr bool operator==(derived_type const lhs, component_proxy const rhs) noexcept
716  {
717  return get<index>(lhs) == static_cast<alphabet_type>(rhs);
718  }
719 
721  friend constexpr bool operator==(component_proxy<alphabet_type, index> const lhs, derived_type const rhs) noexcept
722  {
723  return rhs == lhs;
724  }
725 
727  friend constexpr bool operator!=(derived_type const lhs, component_proxy const rhs) noexcept
728  {
729  return get<index>(lhs) != static_cast<alphabet_type>(rhs);
730  }
731 
733  friend constexpr bool operator!=(component_proxy<alphabet_type, index> const lhs, derived_type const rhs) noexcept
734  {
735  return rhs != lhs;
736  }
737 
739  friend constexpr bool operator<(derived_type const lhs, component_proxy const rhs) noexcept
740  {
741  return get<index>(lhs) < static_cast<alphabet_type>(rhs);
742  }
743 
745  friend constexpr bool operator<(component_proxy<alphabet_type, index> const lhs, derived_type const rhs) noexcept
746  {
747  return rhs > lhs;
748  }
749 
751  friend constexpr bool operator<=(derived_type const lhs, component_proxy const rhs) noexcept
752  {
753  return get<index>(lhs) <= static_cast<alphabet_type>(rhs);
754  }
755 
757  friend constexpr bool operator<=(component_proxy<alphabet_type, index> const lhs, derived_type const rhs) noexcept
758  {
759  return rhs >= lhs;
760  }
761 
763  friend constexpr bool operator>(derived_type const lhs, component_proxy const rhs) noexcept
764  {
765  return get<index>(lhs) > static_cast<alphabet_type>(rhs);
766  }
767 
769  friend constexpr bool operator>(component_proxy<alphabet_type, index> const lhs, derived_type const rhs) noexcept
770  {
771  return rhs < lhs;
772  }
773 
775  friend constexpr bool operator>=(derived_type const lhs, component_proxy const rhs) noexcept
776  {
777  return get<index>(lhs) >= static_cast<alphabet_type>(rhs);
778  }
779 
781  friend constexpr bool operator>=(component_proxy<alphabet_type, index> const lhs, derived_type const rhs) noexcept
782  {
783  return rhs <= lhs;
784  }
786 };
787 
788 } // namespace seqan3
789 
790 namespace std
791 {
792 
800 template <std::size_t i, seqan3::detail::alphabet_tuple_like tuple_t>
801 struct tuple_element<i, tuple_t>
802 {
804  using type = seqan3::list_traits::at<i, typename tuple_t::seqan3_required_types>;
805 };
806 
814 template <seqan3::detail::alphabet_tuple_like tuple_t>
815 struct tuple_size<tuple_t> :
816  public std::integral_constant<size_t, seqan3::list_traits::size<typename tuple_t::seqan3_required_types>>
817 {};
818 
819 } // namespace std
Core alphabet concept and free function/type trait wrappers.
Provides seqan3::alphabet_base.
Provides seqan3::alphabet_proxy.
The <concepts> header from C++20's standard library.
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition: alphabet/concept.hpp:293
requires requires
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition: alphabet/concept.hpp:164
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: alphabet/concept.hpp:155
requires constexpr seqan3::detail::template_specialisation_of< list_t, seqan3::type_list > bool contains
Whether a type occurs in a type list or not.
Definition: type_list/traits.hpp:252
constexpr ptrdiff_t count
Count the occurrences of a type in a pack.
Definition: type_pack/traits.hpp:164
constexpr size_t size
The size of a type pack.
Definition: type_pack/traits.hpp:146
Provides metaprogramming utilities for integer types.
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
constexpr auto const & get(configuration< configs_t... > const &config) noexcept
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: configuration.hpp:415
SeqAn specific customisations in the standard namespace.
T operator!=(T... args)
Type that contains multiple types.
Definition: type_list.hpp:29
seqan3::list_traits::at< i, typename tuple_t::seqan3_required_types > type
Element type.
Definition: alphabet_tuple_base.hpp:804
Provides seqan3::detail::transformation_trait_or.
Provides traits for seqan3::type_list.
Provides seqan3::type_list.
Provides algorithms for meta programming, parameter packs and seqan3::type_list.
Provides various traits for template packs.
Provides seqan3::tuple_like.