SeqAn3  3.0.0
The Modern C++ library for sequence analysis.
alphabet_tuple_base.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2019, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2019, 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 <utility>
17 
18 #include <meta/meta.hpp>
19 
31 #include <seqan3/std/concepts>
32 
33 namespace seqan3::detail
34 {
35 
51 // anchor is false
52 template <typename tuple_t, typename tuple_derived_t, template <typename> typename fun_t, typename other_t>
53 inline bool constexpr one_component_is = false;
54 
56 
57 // default
58 template <typename ... tuple_comps,
59  typename tuple_derived_t,
60  template <typename> typename fun_t,
61  typename other_t>
62 inline bool constexpr one_component_is<alphabet_tuple_base<tuple_derived_t, tuple_comps...>,
63  tuple_derived_t,
64  fun_t,
65  other_t> =
66  !meta::empty<meta::find_if<meta::list<tuple_comps...>, fun_t<other_t>>>::value;
67  //TODO do without meta
68 
69 // guard against self
70 template <typename ... tuple_comps,
71  typename tuple_derived_t,
72  template <typename> typename fun_t>
73 inline bool constexpr one_component_is<alphabet_tuple_base<tuple_derived_t, tuple_comps...>,
74  tuple_derived_t,
75  fun_t,
76  alphabet_tuple_base<tuple_derived_t, tuple_comps...>> = false;
77 
78 // guard against self (derived)
79 template <typename ... tuple_comps,
80  typename tuple_derived_t,
81  template <typename> typename fun_t>
82 inline bool constexpr one_component_is<alphabet_tuple_base<tuple_derived_t, tuple_comps...>,
83  tuple_derived_t,
84  fun_t,
85  tuple_derived_t> = false;
86 
87 // guard against types that have conversion operators to derived
88 template <typename ... tuple_comps,
89  typename tuple_derived_t,
90  template <typename> typename fun_t,
91  typename other_t>
92  requires ConvertibleToByMember<other_t, tuple_derived_t>
93 inline bool constexpr one_component_is<alphabet_tuple_base<tuple_derived_t, tuple_comps...>,
94  tuple_derived_t,
95  fun_t,
96  other_t> = false;
97 
98 // guard against components
99 template <typename ... tuple_comps,
100  typename tuple_derived_t,
101  template <typename> typename fun_t,
102  typename other_t>
103  requires type_in_pack_v<other_t, tuple_comps...>
104 // requires meta::in<recursive_tuple_components<alphabet_tuple_base<tuple_derived_t, tuple_comps...>>::type,
105 // other_t>::value
106 inline bool constexpr one_component_is<alphabet_tuple_base<tuple_derived_t, tuple_comps...>,
107  tuple_derived_t,
108  fun_t,
109  other_t> = false;
110 
111 // during comparisons, guard against types that could be converted to self (because that is preferred)
112 // (may not be done during assignment or construction because of recursiveness)
113 template <typename ... tuple_comps,
114  typename tuple_derived_t,
115  typename other_t>
116  requires ImplicitlyConvertibleTo<other_t, tuple_derived_t>
117 inline bool constexpr one_component_is<alphabet_tuple_base<tuple_derived_t, tuple_comps...>,
118  tuple_derived_t,
119  weakly_equality_comparable_with,
120  other_t> = false;
121 template <typename ... tuple_comps,
122  typename tuple_derived_t,
123  typename other_t>
124  requires ImplicitlyConvertibleTo<other_t, tuple_derived_t>
125 inline bool constexpr one_component_is<alphabet_tuple_base<tuple_derived_t, tuple_comps...>,
126  tuple_derived_t,
127  weakly_ordered_with,
128  other_t> = false;
130 
131 } // namespace seqan3::detail
132 
133 namespace seqan3
134 {
135 
136 // forwards
138 template <typename t>
139 decltype(auto) get();
140 
141 template <size_t i>
142 decltype(auto) get();
144 
182 template <typename derived_type,
183  typename ...component_types>
185  requires (detail::WritableConstexprSemialphabet<component_types> && ...) &&
186  (!std::is_reference_v<component_types> && ...)
189  public alphabet_base<derived_type,
190  (1 * ... * alphabet_size<component_types>),
191  void> // no char type, because this is only semi_alphabet
192 {
193 private:
195  using base_t = alphabet_base<derived_type,
196  (1 * ... * alphabet_size<component_types>),
197  void>; // no char type, because this is only semi_alphabet
198 
200  using component_list = meta::list<component_types...>;
201 
203  template <typename type>
204  static constexpr bool is_component =
205  meta::in<component_list, type>::value;
206 
208  template <typename type>
209  static constexpr bool is_unique_component =
210  is_component<type> &&
211  (meta::find_index<component_list, type>::value == meta::reverse_find_index<component_list, type>::value);
212 
217  template <typename alphabet_type, size_t index>
218  class component_proxy : public alphabet_proxy<component_proxy<alphabet_type, index>, alphabet_type>
219  {
220  private:
224  friend base_t;
225 
227  alphabet_tuple_base *parent;
228 
230  constexpr void on_update() noexcept
231  {
232  parent->assign_rank(
233  parent->to_rank()
234  - parent->template to_component_rank<index>() * alphabet_tuple_base::cummulative_alph_sizes[index]
235  + to_rank() * alphabet_tuple_base::cummulative_alph_sizes[index]);
236  }
237 
241  using typename base_t::rank_type;
242  using typename base_t::char_type;
243  using typename base_t::phred_type;
245 
246  public:
247  //Import from base type:
248  using base_t::to_rank;
249  using base_t::alphabet_size;
250  using base_t::operator=;
251 
255  constexpr component_proxy() : base_t{}, parent{} {}
256  constexpr component_proxy(component_proxy const &) = default;
257  constexpr component_proxy(component_proxy &&) = default;
258  constexpr component_proxy & operator=(component_proxy const &) = default;
259  constexpr component_proxy & operator=(component_proxy &&) = default;
260  ~component_proxy() = default;
261 
262  constexpr component_proxy(alphabet_type const l, alphabet_tuple_base & p) :
263  base_t{l}, parent{&p}
264  {}
265 
266  // Does not inherit the base's constructor for alphabet_type so as not to cause ambiguity
268  };
269 
273  constexpr alphabet_tuple_base() noexcept : base_t{} {}
274  constexpr alphabet_tuple_base(alphabet_tuple_base const &) = default;
275  constexpr alphabet_tuple_base(alphabet_tuple_base &&) = default;
276  constexpr alphabet_tuple_base & operator=(alphabet_tuple_base const &) = default;
277  constexpr alphabet_tuple_base & operator=(alphabet_tuple_base &&) = default;
278  ~alphabet_tuple_base() = default;
279 
280  using base_t::base_t;
282 
285  friend derived_type;
286 
287  // Import from base:
288  using typename base_t::rank_type;
289 
290 public:
291  // Import from base:
292  using base_t::alphabet_size;
293  using base_t::to_rank;
294  using base_t::assign_rank;
295 
298  using seqan3_tuple_components = component_list;
301  using seqan3_recursive_tuple_components =
302  meta::concat<component_list,
303  detail::transformation_trait_or_t<detail::recursive_tuple_components<component_types>,
304  meta::list<>>...>;
305 
313  constexpr alphabet_tuple_base(component_types ... components) noexcept
315  {
316  assign_rank(rank_sum_helper(components..., std::make_index_sequence<sizeof...(component_types)>{}));
317  }
318 
328  template <typename component_type>
330  requires is_unique_component<component_type>
332  constexpr explicit alphabet_tuple_base(component_type const alph) noexcept : alphabet_tuple_base{}
333  {
334  get<component_type>(*this) = alph;
335  }
336 
350  template <typename indirect_component_type>
352  requires detail::one_component_is<alphabet_tuple_base, derived_type, detail::implicitly_convertible_from, indirect_component_type>
354  constexpr explicit alphabet_tuple_base(indirect_component_type const alph) noexcept : alphabet_tuple_base{}
355  {
356  using component_type = meta::front<meta::find_if<component_list, detail::implicitly_convertible_from<indirect_component_type>>>;
357  component_type tmp(alph); // delegate construction
358  get<component_type>(*this) = tmp;
359  }
360 
362  template <typename indirect_component_type>
363  requires !detail::one_component_is<alphabet_tuple_base, derived_type, detail::implicitly_convertible_from, indirect_component_type> &&
364  detail::one_component_is<alphabet_tuple_base, derived_type, detail::constructible_from, indirect_component_type>
365  constexpr explicit alphabet_tuple_base(indirect_component_type const alph) noexcept : alphabet_tuple_base{}
366  {
367  using component_type = meta::front<meta::find_if<component_list, detail::constructible_from<indirect_component_type>>>;
368  component_type tmp(alph); // delegate construction
369  get<component_type>(*this) = tmp;
370  }
372 
382  template <typename component_type>
384  requires is_unique_component<component_type>
386  constexpr derived_type & operator=(component_type const alph) noexcept
387  {
388  get<component_type>(*this) = alph;
389  return static_cast<derived_type &>(*this);
390  }
391 
401  template <typename indirect_component_type>
403  requires detail::one_component_is<alphabet_tuple_base, derived_type, detail::assignable_from, indirect_component_type>
405  constexpr derived_type & operator=(indirect_component_type const alph) noexcept
406  {
407  using component_type = meta::front<meta::find_if<component_list, detail::assignable_from<indirect_component_type>>>;
408  get<component_type>(*this) = alph; // delegate assignment
409  return static_cast<derived_type &>(*this);
410  }
412  // If not assignable but implicit convertible, convert first and assign afterwards
413  template <typename indirect_component_type>
415  requires !detail::one_component_is<alphabet_tuple_base, derived_type, detail::assignable_from, indirect_component_type> &&
416  detail::one_component_is<alphabet_tuple_base, derived_type, detail::implicitly_convertible_from, indirect_component_type>
418  constexpr derived_type & operator=(indirect_component_type const alph) noexcept
419  {
420  using component_type = meta::front<meta::find_if<component_list, detail::implicitly_convertible_from<indirect_component_type>>>;
421  component_type tmp(alph);
422  get<component_type>(*this) = tmp;
423  return static_cast<derived_type &>(*this);
424  }
427 
436  template <size_t index>
437  friend constexpr auto get(alphabet_tuple_base & l) noexcept
438  {
439  static_assert(index < sizeof...(component_types), "Index out of range.");
440 
441  using t = meta::at_c<component_list, index>;
442  t val{};
443 
445  assign_rank_to(l.to_component_rank<index>(), val);
446 
447  return component_proxy<t, index>{val, l};
448  }
449 
454  template <typename type>
455  friend constexpr auto get(alphabet_tuple_base & l) noexcept
457  requires is_unique_component<type>
459  {
460  return get<meta::find_index<component_list, type>::value>(l);
461  }
462 
467  template <size_t index>
468  friend constexpr auto get(alphabet_tuple_base const & l) noexcept
469  {
470  static_assert(index < sizeof...(component_types), "Index out of range.");
471 
472  using t = meta::at_c<component_list, index>;
473  t val{};
474 
476  assign_rank_to(l.to_component_rank<index>(), val);
477 
478  return val;
479  }
480 
485  template <typename type>
486  friend constexpr type get(alphabet_tuple_base const & l) noexcept
488  requires is_unique_component<type>
490  {
491  return get<meta::find_index<component_list, type>::value>(l);
492  }
493 
496  template <typename type>
497  constexpr operator type() const noexcept
499  requires is_unique_component<type>
501  {
502  return get<type>(*this);
503  }
505 
511  template <typename indirect_component_type>
512  constexpr bool operator==(indirect_component_type const rhs) const noexcept
514  requires detail::one_component_is<alphabet_tuple_base, derived_type, detail::weakly_equality_comparable_with, indirect_component_type>
516  {
517  using component_type = meta::front<meta::find_if<component_list, detail::weakly_equality_comparable_with<indirect_component_type>>>;
518  return get<component_type>(*this) == rhs;
519  }
520 
521  template <typename indirect_component_type>
522  constexpr bool operator!=(indirect_component_type const rhs) const noexcept
524  requires detail::one_component_is<alphabet_tuple_base, derived_type, detail::weakly_equality_comparable_with, indirect_component_type>
526  {
527  using component_type = meta::front<meta::find_if<component_list, detail::weakly_equality_comparable_with<indirect_component_type>>>;
528  return get<component_type>(*this) != rhs;
529  }
530 
531  template <typename indirect_component_type>
532  constexpr bool operator<(indirect_component_type const rhs) const noexcept
534  requires detail::one_component_is<alphabet_tuple_base, derived_type, detail::weakly_ordered_with, indirect_component_type>
536  {
537  using component_type = meta::front<meta::find_if<component_list, detail::weakly_ordered_with<indirect_component_type>>>;
538  return get<component_type>(*this) < rhs;
539  }
540 
541  template <typename indirect_component_type>
542  constexpr bool operator>(indirect_component_type const rhs) const noexcept
544  requires detail::one_component_is<alphabet_tuple_base, derived_type, detail::weakly_ordered_with, indirect_component_type>
546  {
547  using component_type = meta::front<meta::find_if<component_list, detail::weakly_ordered_with<indirect_component_type>>>;
548  return get<component_type>(*this) > rhs;
549  }
550 
551  template <typename indirect_component_type>
552  constexpr bool operator<=(indirect_component_type const rhs) const noexcept
554  requires detail::one_component_is<alphabet_tuple_base, derived_type, detail::weakly_ordered_with, indirect_component_type>
556  {
557  using component_type = meta::front<meta::find_if<component_list, detail::weakly_ordered_with<indirect_component_type>>>;
558  return get<component_type>(*this) <= rhs;
559  }
560 
561  template <typename indirect_component_type>
562  constexpr bool operator>=(indirect_component_type const rhs) const noexcept
564  requires detail::one_component_is<alphabet_tuple_base, derived_type, detail::weakly_ordered_with, indirect_component_type>
566  {
567  using component_type = meta::front<meta::find_if<component_list, detail::weakly_ordered_with<indirect_component_type>>>;
568  return get<component_type>(*this) >= rhs;
569  }
571 
572 private:
574  template <size_t index>
575  constexpr rank_type to_component_rank() const noexcept
576  {
577  return (to_rank() / cummulative_alph_sizes[index]) % seqan3::alphabet_size<meta::at_c<component_list, index>>;
578  }
579 
581  static constexpr std::array<rank_type, component_list::size()> cummulative_alph_sizes
582  {
583  [] () constexpr
584  {
585  // create array (1, |sigma1|, |sigma1|*|sigma2|, ... , |sigma1|*...*|sigmaN|)
587  ret[0] = 1;
588  size_t count = 1;
589  meta::for_each(meta::reverse<component_list>{}, [&] (auto alph) constexpr
590  {
591  ret[count] = static_cast<rank_type>(seqan3::alphabet_size<decltype(alph)> * ret[count - 1]);
592  ++count;
593  });
594 
595  // reverse and strip one: (|sigma1|*...*|sigmaN-1|, ... |sigma1|*|sigma2|, |sigma1|, 1)
596  // reverse order guarantees that the first alphabet is the most significant rank contributer
597  // resulting in element-wise alphabetical ordering on comparison
599  for (size_t i = 0; i < component_list::size(); ++i)
600  ret2[i] = ret[component_list::size() - i - 1];
601 
602  return ret2;
603  }()
604  };
605 
607  template <std::size_t ...idx>
608  static constexpr rank_type rank_sum_helper(component_types ... components, std::index_sequence<idx...> const &) noexcept
609  {
610  using seqan3::to_rank;
611  return ((to_rank(components) * cummulative_alph_sizes[idx]) + ...);
612  }
613 };
614 
620 template <typename indirect_component_type, typename derived_type, typename ...component_types>
622  requires detail::WeaklyEqualityComparableByMembersWith<derived_type, indirect_component_type> &&
623  !detail::WeaklyEqualityComparableByMembersWith<indirect_component_type, derived_type>
625 constexpr bool operator==(indirect_component_type const lhs,
626  alphabet_tuple_base<derived_type, component_types...> const rhs) noexcept
627 {
628  return rhs == lhs;
629 }
630 
631 template <typename indirect_component_type, typename derived_type, typename ...indirect_component_types>
633  requires detail::WeaklyEqualityComparableByMembersWith<derived_type, indirect_component_type> &&
634  !detail::WeaklyEqualityComparableByMembersWith<indirect_component_type, derived_type>
636 constexpr bool operator!=(indirect_component_type const lhs,
637  alphabet_tuple_base<derived_type, indirect_component_types...> const rhs) noexcept
638 {
639  return rhs != lhs;
640 }
641 
642 template <typename indirect_component_type, typename derived_type, typename ...indirect_component_types>
644  requires detail::WeaklyOrderedByMembersWith<derived_type, indirect_component_type> &&
645  !detail::WeaklyOrderedByMembersWith<indirect_component_type, derived_type>
647 constexpr bool operator<(indirect_component_type const lhs,
648  alphabet_tuple_base<derived_type, indirect_component_types...> const rhs) noexcept
649 {
650  return rhs > lhs;
651 }
652 
653 template <typename indirect_component_type, typename derived_type, typename ...indirect_component_types>
655  requires detail::WeaklyOrderedByMembersWith<derived_type, indirect_component_type> &&
656  !detail::WeaklyOrderedByMembersWith<indirect_component_type, derived_type>
658 constexpr bool operator>(indirect_component_type const lhs,
659  alphabet_tuple_base<derived_type, indirect_component_types...> const rhs) noexcept
660 {
661  return rhs < lhs;
662 }
663 
664 template <typename indirect_component_type, typename derived_type, typename ...indirect_component_types>
666  requires detail::WeaklyOrderedByMembersWith<derived_type, indirect_component_type> &&
667  !detail::WeaklyOrderedByMembersWith<indirect_component_type, derived_type>
669 constexpr bool operator<=(indirect_component_type const lhs,
670  alphabet_tuple_base<derived_type, indirect_component_types...> const rhs) noexcept
671 {
672  return rhs >= lhs;
673 }
674 
675 template <typename indirect_component_type, typename derived_type, typename ...indirect_component_types>
677  requires detail::WeaklyOrderedByMembersWith<derived_type, indirect_component_type> &&
678  !detail::WeaklyOrderedByMembersWith<indirect_component_type, derived_type>
680 constexpr bool operator>=(indirect_component_type const lhs,
681  alphabet_tuple_base<derived_type, indirect_component_types...> const rhs) noexcept
682 {
683  return rhs <= lhs;
684 }
686 
687 } // namespace seqan3
688 
689 namespace std
690 {
691 
697 template <std::size_t i, seqan3::detail::AlphabetTupleBase tuple_t>
698 struct tuple_element<i, tuple_t>
699 {
701  using type = meta::at_c<typename tuple_t::seqan3_tuple_components, i>;
702 };
703 
709 template <seqan3::detail::AlphabetTupleBase tuple_t>
710 struct tuple_size<tuple_t> :
711  public std::integral_constant<size_t, tuple_t::seqan3_tuple_components::size()>
712 {};
713 
714 } // namespace std
Provides concepts for core language types and relations that don&#39;t have concepts in C++20 (yet)...
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition: concept.hpp:207
A CRTP-base that eases the definition of proxy types returned in place of regular alphabets...
Definition: alphabet_proxy.hpp:131
constexpr derived_type & operator=(component_type const alph) noexcept
Assignment via a value of one of the components.
Definition: alphabet_tuple_base.hpp:386
Provides metaprogramming utilities for integer types.
constexpr alphabet_tuple_base(component_type const alph) noexcept
Construction via a value of one of the components.
Definition: alphabet_tuple_base.hpp:332
T operator>(T... args)
Provides seqan3::detail::transformation_trait_or.
Provides unary type traits on a set of types, usually provided as template argument pack...
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:103
SeqAn specific customisations in the standard namespace.
constexpr auto const & get(configuration< configs_t... > const &config) noexcept
Definition: configuration.hpp:578
::ranges::size size
Alias for ranges::size. Obtains the size of a range whose size can be calculated in constant time...
Definition: ranges:189
The main SeqAn3 namespace.
Provides implementation detail for seqan3::alphabet_variant and seqan3::alphabet_tuple_base.
constexpr derived_type & assign_rank(rank_type const c) noexcept
Assign from a numeric value.
Definition: alphabet_base.hpp:166
Provides seqan3::TupleLike.
The CRTP base for a combined alphabet that contains multiple values of different alphabets at the sam...
Definition: alphabet_tuple_base.hpp:188
The Concepts library.
constexpr alphabet_tuple_base(indirect_component_type const alph) noexcept
Construction via a value of a subtype that is assignable to one of the components.
Definition: alphabet_tuple_base.hpp:354
Free function/type trait wrappers for alphabets with member functions/types.
Provides utility functions for tuple like interfaces.
Provides seqan3::alphabet_base.
T count(T... args)
constexpr derived_type & operator=(indirect_component_type const alph) noexcept
Assignment via a value of a subtype that is assignable to one of the components.
Definition: alphabet_tuple_base.hpp:405
Definition: aligned_sequence_concept.hpp:35
meta::at_c< typename tuple_t::seqan3_tuple_components, i > type
Element type.
Definition: alphabet_tuple_base.hpp:701
constexpr rank_type to_rank() const noexcept
Return the letter&#39;s numeric value (rank in the alphabet).
Definition: alphabet_base.hpp:117
::ranges::empty empty
Alias for ranges::empty. Checks whether a range is empty.
Definition: ranges:194
Core alphabet concept and free function/type trait wrappers.
A CRTP-base that makes defining a custom alphabet easier.
Definition: alphabet_base.hpp:52
Quality alphabet concept.
constexpr auto alphabet_size
A type trait that holds the size of a (semi-)alphabet.
Definition: concept.hpp:678