SeqAn3  3.0.3
The Modern C++ library for sequence analysis.
alphabet_proxy.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2021, 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 <seqan3/std/concepts>
16 
23 
24 namespace seqan3
25 {
26 
56 template <typename derived_type, writable_semialphabet alphabet_type>
58  requires std::regular<alphabet_type>
60 class alphabet_proxy : public
61  std::conditional_t<std::is_class_v<alphabet_type>,
62  alphabet_type,
63  alphabet_base<derived_type,
64  alphabet_size<alphabet_type>,
65  detail::valid_template_spec_or_t<void, alphabet_char_t, alphabet_type>>>
66 {
67 private:
69  using base_t =
71  alphabet_type, // inherit from emulated type if possible
72  alphabet_base<derived_type, // else: alphabet_base
73  alphabet_size<alphabet_type>,
74  detail::valid_template_spec_or_t<void, alphabet_char_t, alphabet_type>>>;
75 
77  friend base_t;
78 
80  using char_type = detail::valid_template_spec_or_t<char, alphabet_char_t, alphabet_type>;
81 
83  using phred_type = detail::valid_template_spec_or_t<int8_t, alphabet_phred_t, alphabet_type>;
84 
85 private:
89  constexpr alphabet_proxy() noexcept = default;
90  constexpr alphabet_proxy(alphabet_proxy const &) = default;
91  constexpr alphabet_proxy(alphabet_proxy &&) = default;
92  constexpr alphabet_proxy & operator=(alphabet_proxy const &) = default;
93  constexpr alphabet_proxy & operator=(alphabet_proxy &&) = default;
94  ~alphabet_proxy() = default;
95 
97  constexpr alphabet_proxy(alphabet_type const a) noexcept
99  requires std::is_class_v<alphabet_type>
101  : base_t{a}
102  {}
103 
105  constexpr alphabet_proxy(alphabet_type const a) noexcept
107  requires (!std::is_class_v<alphabet_type>)
109  : base_t{}
110  {
111  base_t::assign_rank(seqan3::to_rank(a));
112  }
113 
115  constexpr derived_type & operator=(alphabet_type const & c) noexcept
116  {
117  if constexpr (std::is_class_v<alphabet_type>)
118  seqan3::assign_rank_to(seqan3::to_rank(c), static_cast<alphabet_type &>(*this));
119  else
120  base_t::assign_rank(seqan3::to_rank(c));
121 
122  static_cast<derived_type &>(*this).on_update(); // <- this invokes the actual proxy behaviour!
123  return static_cast<derived_type &>(*this);
124  }
125 
127  template <typename indirect_assignable_type>
128  constexpr derived_type & operator=(indirect_assignable_type const & c) noexcept
132  {
133  alphabet_type a{};
134  a = c;
135  return operator=(a);
136  }
138 
140  friend derived_type;
141 
142 public:
144  static constexpr auto alphabet_size = seqan3::alphabet_size<alphabet_type>;
145 
152  constexpr derived_type & assign_rank(alphabet_rank_t<alphabet_type> const r) noexcept
153  {
154  alphabet_type tmp{};
155  assign_rank_to(r, tmp);
156  return operator=(tmp);
157  }
158 
160  constexpr derived_type & assign_char(char_type const c) noexcept
164  {
165  alphabet_type tmp{};
166  assign_char_to(c, tmp);
167  return operator=(tmp);
168  }
169 
171  constexpr derived_type & assign_phred(phred_type const c) noexcept
175  {
176  alphabet_type tmp{};
177  assign_phred_to(c, tmp);
178  return operator=(tmp);
179  }
181 
187  constexpr operator alphabet_type() const noexcept
188  {
189  if constexpr (std::is_class_v<alphabet_type>)
190  return *this;
191  else
192  return assign_rank_to(base_t::to_rank(), alphabet_type{});
193 
194  /* Instead of static_cast'ing to the alphabet_type which also considers the constructors of the alphabet_type,
195  * we explicitly invoke this operator in various places.
196  * This prevents errors associated with using alphabet_type's constructors.
197  *
198  * This is one of error cases:
199  * The tuple composite seqan3::qualified returns a component_proxy which inherits from alphabet_proxy_base.
200  * The qualified alphabet itself inherits from phred_base.
201  * Now when accessing get<1>(seq_qual_alph) we want to call to_phred at some point because we want the quality,
202  * therefore the to_phred function from alphabet_proxy is called, but this function did a static_cast to the
203  * derived type which is calling the constructor from phred_base. Unfortunately now, the generic phred_base
204  * constructor uses `assign_phred_to(to_phred(other), static_cast<derived_type &>(*this))`; (here) which again
205  * tries to call to_phred of the alphabet_proxy => infinite loop :boom:
206  */
207  }
208 
210  template <typename other_t>
212  requires (!std::is_class_v<alphabet_type>) && std::convertible_to<alphabet_type, other_t>
214  constexpr operator other_t() const noexcept
215  {
216  return operator alphabet_type();
217  }
218 
220  constexpr auto to_rank() const noexcept
221  {
222  return seqan3::to_rank(operator alphabet_type());
223  }
224 
226  constexpr auto to_char() const noexcept
228  requires alphabet<alphabet_type>
230  {
231  return seqan3::to_char(operator alphabet_type());
232  }
233 
235  constexpr auto to_phred() const noexcept
237  requires quality_alphabet<alphabet_type>
239  {
240  return seqan3::to_phred(operator alphabet_type());
241  }
242 
244  constexpr alphabet_type complement() const noexcept
246  requires nucleotide_alphabet<alphabet_type>
248  {
249  return seqan3::complement(operator alphabet_type());
250  }
251 
253  static constexpr bool char_is_valid(char_type const c) noexcept
257  {
258  return char_is_valid_for<alphabet_type>(c);
259  }
261 
267 private:
269  template <typename t>
270  static constexpr bool is_alphabet_comparable_with = !std::is_same_v<derived_type, t> &&
271  detail::weakly_equality_comparable_with<alphabet_type, t>;
272 
273 public:
275  template <typename t>
276  friend constexpr auto operator==(derived_type const lhs, t const rhs) noexcept
278  {
279  return (lhs.operator alphabet_type() == rhs);
280  }
281 
283  template <typename t>
284  friend constexpr auto operator==(t const lhs, derived_type const rhs) noexcept
286  {
287  return (rhs == lhs);
288  }
289 
291  template <typename t>
292  friend constexpr auto operator!=(derived_type const lhs, t const rhs) noexcept
294  {
295  return !(lhs == rhs);
296  }
297 
299  template <typename t>
300  friend constexpr auto operator!=(t const lhs, derived_type const rhs) noexcept
302  {
303  return (rhs != lhs);
304  }
306 };
307 
308 } // namespace seqan3
Provides seqan3::nucleotide_alphabet.
Quality alphabet concept.
Provides seqan3::alphabet_base.
A CRTP-base that makes defining a custom alphabet easier.
Definition: alphabet_base.hpp:81
A CRTP-base that eases the definition of proxy types returned in place of regular alphabets.
Definition: alphabet_proxy.hpp:66
constexpr derived_type & assign_rank(alphabet_rank_t< alphabet_type > const r) noexcept
Assigns a rank.
Definition: alphabet_proxy.hpp:152
static constexpr bool char_is_valid(char_type const c) noexcept
Delegate to the emulated type's validator.
Definition: alphabet_proxy.hpp:253
static constexpr auto alphabet_size
The alphabet size.
Definition: alphabet_proxy.hpp:144
constexpr friend auto operator==(t const lhs, derived_type const rhs) noexcept -> std::enable_if_t< is_alphabet_comparable_with< t >, bool >
Allow (in-)equality comparison with types that the emulated type is comparable with.
Definition: alphabet_proxy.hpp:284
constexpr friend auto operator!=(t const lhs, derived_type const rhs) noexcept -> std::enable_if_t< is_alphabet_comparable_with< t >, bool >
Allow (in-)equality comparison with types that the emulated type is comparable with.
Definition: alphabet_proxy.hpp:300
constexpr friend auto operator==(derived_type const lhs, t const rhs) noexcept -> std::enable_if_t< is_alphabet_comparable_with< t >, bool >
Allow (in-)equality comparison with types that the emulated type is comparable with.
Definition: alphabet_proxy.hpp:276
constexpr auto to_phred() const noexcept
Returns the Phred score.
Definition: alphabet_proxy.hpp:235
constexpr alphabet_type complement() const noexcept
Returns the complement.
Definition: alphabet_proxy.hpp:244
constexpr auto to_char() const noexcept
Returns the character.
Definition: alphabet_proxy.hpp:226
constexpr derived_type & assign_char(char_type const c) noexcept
Assigns a character.
Definition: alphabet_proxy.hpp:160
constexpr derived_type & assign_phred(phred_type const c) noexcept
Assigns a Phred score.
Definition: alphabet_proxy.hpp:171
constexpr auto to_rank() const noexcept
Returns the rank.
Definition: alphabet_proxy.hpp:220
constexpr friend auto operator!=(derived_type const lhs, t const rhs) noexcept -> std::enable_if_t< is_alphabet_comparable_with< t >, bool >
Allow (in-)equality comparison with types that the emulated type is comparable with.
Definition: alphabet_proxy.hpp:292
The Concepts library.
Provides type traits for working with templates.
Provides concepts for core language types and relations that don't have concepts in C++20 (yet).
constexpr auto assign_char_to
Assign a character to an alphabet object.
Definition: concept.hpp:523
constexpr auto to_char
Return the char representation of an alphabet object.
Definition: concept.hpp:384
decltype(seqan3::to_rank(std::declval< semi_alphabet_type >())) alphabet_rank_t
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank.
Definition: concept.hpp:164
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition: concept.hpp:291
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:155
constexpr auto complement
Return the complement of a nucleotide object.
Definition: concept.hpp:104
constexpr auto to_phred
The public getter function for the Phred representation of a quality score.
Definition: concept.hpp:100
constexpr auto assign_phred_to
Assign a Phred score to a quality alphabet object.
Definition: concept.hpp:231
The generic alphabet concept that covers most data types used in ranges.
A concept that indicates whether an alphabet represents nucleotides.
A concept that indicates whether an alphabet represents quality scores.
Resolves to std::is_assignable_v<t>.
Refines seqan3::alphabet and adds assignability.
A concept that indicates whether a writable alphabet represents quality scores.
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
Provides various type traits on generic types.