SeqAn3  3.0.1
The Modern C++ library for sequence analysis.
alphabet_proxy.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 
21 #include <seqan3/std/concepts>
22 
23 namespace seqan3
24 {
25 
55 template <typename derived_type, writable_semialphabet alphabet_type>
59 class alphabet_proxy : public
60  std::conditional_t<std::is_class_v<alphabet_type>,
61  alphabet_type,
62  alphabet_base<derived_type,
63  alphabet_size<alphabet_type>,
64  detail::valid_template_spec_or_t<void, alphabet_char_t, alphabet_type>>>
65 {
66 private:
68  using base_t =
70  alphabet_type, // inherit from emulated type if possible
71  alphabet_base<derived_type, // else: alphabet_base
72  alphabet_size<alphabet_type>,
73  detail::valid_template_spec_or_t<void, alphabet_char_t, alphabet_type>>>;
74 
76  friend base_t;
77 
79  using char_type = detail::valid_template_spec_or_t<char, alphabet_char_t, alphabet_type>;
80 
82  using phred_type = detail::valid_template_spec_or_t<int8_t, alphabet_phred_t, alphabet_type>;
83 
84 private:
88  constexpr alphabet_proxy() noexcept = default;
89  constexpr alphabet_proxy(alphabet_proxy const &) = default;
90  constexpr alphabet_proxy(alphabet_proxy &&) = default;
91  constexpr alphabet_proxy & operator=(alphabet_proxy const &) = default;
92  constexpr alphabet_proxy & operator=(alphabet_proxy &&) = default;
93  ~alphabet_proxy() = default;
94 
96  constexpr alphabet_proxy(alphabet_type const a) noexcept
98  requires std::is_class_v<alphabet_type>
100  : base_t{a}
101  {}
102 
104  constexpr alphabet_proxy(alphabet_type const a) noexcept
106  requires !std::is_class_v<alphabet_type>
108  : base_t{}
109  {
110  base_t::assign_rank(seqan3::to_rank(a));
111  }
112 
114  constexpr derived_type & operator=(alphabet_type const & c) noexcept
115  {
116  if constexpr (std::is_class_v<alphabet_type>)
117  seqan3::assign_rank_to(seqan3::to_rank(c), static_cast<alphabet_type &>(*this));
118  else
119  base_t::assign_rank(seqan3::to_rank(c));
120 
121  static_cast<derived_type &>(*this).on_update(); // <- this invokes the actual proxy behaviour!
122  return static_cast<derived_type &>(*this);
123  }
124 
126  template <typename indirect_assignable_type>
127  constexpr derived_type & operator=(indirect_assignable_type const & c) noexcept
131  {
132  alphabet_type a{};
133  a = c;
134  return operator=(a);
135  }
137 
139  friend derived_type;
140 
141 public:
143  static constexpr auto alphabet_size = seqan3::alphabet_size<alphabet_type>;
144 
150  constexpr derived_type & assign_rank(alphabet_rank_t<alphabet_type> const r) noexcept
152  {
153  alphabet_type tmp{};
154  assign_rank_to(r, tmp);
155  return operator=(tmp);
156  }
157 
159  constexpr derived_type & assign_char(char_type const c) noexcept
163  {
164  alphabet_type tmp{};
165  assign_char_to(c, tmp);
166  return operator=(tmp);
167  }
168 
170  constexpr derived_type & assign_phred(phred_type const c) noexcept
174  {
175  alphabet_type tmp{};
176  assign_phred_to(c, tmp);
177  return operator=(tmp);
178  }
180 
185  constexpr operator alphabet_type() const noexcept
187  {
188  if constexpr (std::is_class_v<alphabet_type>)
189  return *this;
190  else
191  return assign_rank_to(base_t::to_rank(), alphabet_type{});
192 
193  /* Instead of static_cast'ing to the alphabet_type which also considers the constructors of the alphabet_type,
194  * we explicitly invoke this operator in various places.
195  * This prevents errors associated with using alphabet_type's constructors.
196  *
197  * This is one of error cases:
198  * The tuple composite seqan3::qualified returns a component_proxy which inherits from alphabet_proxy_base.
199  * The qualified alphabet itself inherits from quality_base.
200  * Now when accessing get<1>(seq_qual_alph) we want to call to_phred at some point because we want the quality,
201  * therefore the to_phred function from alphabet_proxy is called, but this function did a static_cast to the
202  * derived type which is calling the constructor from quality_base. Unfortunately now, the generic quality_base
203  * constructor uses `assign_phred_to(to_phred(other), static_cast<derived_type &>(*this))`; (here) which again
204  * tries to call to_phred of the alphabet_proxy => infinite loop :boom:
205  */
206  }
207 
209  template <typename other_t>
211  requires (!std::is_class_v<alphabet_type>) && std::convertible_to<alphabet_type, other_t>
213  constexpr operator other_t() const noexcept
214  {
215  return operator alphabet_type();
216  }
217 
219  constexpr auto to_rank() const noexcept
220  {
221  return seqan3::to_rank(operator alphabet_type());
222  }
223 
225  constexpr auto to_char() const noexcept
227  requires alphabet<alphabet_type>
229  {
230  return seqan3::to_char(operator alphabet_type());
231  }
232 
234  constexpr auto to_phred() const noexcept
236  requires quality_alphabet<alphabet_type>
238  {
239  return seqan3::to_phred(operator alphabet_type());
240  }
241 
243  constexpr alphabet_type complement() const noexcept
245  requires nucleotide_alphabet<alphabet_type>
247  {
248  return seqan3::complement(operator alphabet_type());
249  }
250 
252  static constexpr bool char_is_valid(char_type const c) noexcept
256  {
257  return char_is_valid_for<alphabet_type>(c);
258  }
260 
266 private:
268  template <typename t>
269  static constexpr bool is_alphabet_comparable_with = !std::is_same_v<derived_type, t> &&
270  detail::weakly_equality_comparable_with<alphabet_type, t>;
271 
272 public:
274  template <typename t>
275  friend constexpr auto operator==(derived_type const lhs, t const rhs) noexcept
277  {
278  return (lhs.operator alphabet_type() == rhs);
279  }
280 
282  template <typename t>
283  friend constexpr auto operator==(t const lhs, derived_type const rhs) noexcept
285  {
286  return (rhs == lhs);
287  }
288 
290  template <typename t>
291  friend constexpr auto operator!=(derived_type const lhs, t const rhs) noexcept
293  {
294  return !(lhs == rhs);
295  }
296 
298  template <typename t>
299  friend constexpr auto operator!=(t const lhs, derived_type const rhs) noexcept
301  {
302  return (rhs != lhs);
303  }
305 };
306 
307 } // namespace seqan3
seqan3::alphabet_proxy::alphabet_size
static constexpr auto alphabet_size
The alphabet size.
Definition: alphabet_proxy.hpp:143
seqan3::alphabet_proxy::operator==
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:275
alphabet_base.hpp
Provides seqan3::alphabet_base.
seqan3::assign_rank_to
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition: concept.hpp:238
concept.hpp
Provides seqan3::nucleotide_alphabet.
seqan3::alphabet_proxy::assign_phred
constexpr derived_type & assign_phred(phred_type const c) noexcept
Assigns a phred.
Definition: alphabet_proxy.hpp:170
quality_alphabet
A concept that indicates whether an alphabet represents quality scores.
basic.hpp
Provides various type traits on generic types.
seqan3::to_char
constexpr auto to_char
Return the char representation of an alphabet object.
Definition: concept.hpp:320
template_inspection.hpp
Provides seqan3::type_list and auxiliary type traits.
seqan3::alphabet_base
A CRTP-base that makes defining a custom alphabet easier.
Definition: alphabet_base.hpp:51
seqan3::to_rank
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:142
concepts
The Concepts library.
seqan3::alphabet_rank_t
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:151
seqan3::alphabet_proxy::operator!=
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:299
concept.hpp
Quality alphabet concept.
seqan3::alphabet_proxy::assign_rank
constexpr derived_type & assign_rank(alphabet_rank_t< alphabet_type > const r) noexcept
Assigns a rank.
Definition: alphabet_proxy.hpp:151
nucleotide_alphabet
A concept that indicates whether an alphabet represents nucleotides.
std::enable_if_t
seqan3::alphabet_proxy::operator==
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:283
core_language.hpp
Provides concepts for core language types and relations that don't have concepts in C++20 (yet).
seqan3
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:36
seqan3::alphabet_proxy::to_phred
constexpr auto to_phred() const noexcept
Returns the phred score.
Definition: alphabet_proxy.hpp:234
convertible_to
The concept std::convertible_to<From, To> specifies that an expression of the type and value category...
seqan3::alphabet_proxy::char_is_valid
static constexpr bool char_is_valid(char_type const c) noexcept
Delegate to the emulated type's validator.
Definition: alphabet_proxy.hpp:252
seqan3::to_phred
constexpr auto to_phred
The public getter function for the phred representation of a quality score.
Definition: concept.hpp:89
regular
Subsumes std::semiregular and std::equality_comparable.
seqan3::alphabet_proxy::to_char
constexpr auto to_char() const noexcept
Returns the character.
Definition: alphabet_proxy.hpp:225
seqan3::assign_phred_to
constexpr auto assign_phred_to
Assign a phred score to a quality alphabet object.
Definition: concept.hpp:189
alphabet
The generic alphabet concept that covers most data types used in ranges.
weakly_assignable_from
Resolves to std::is_assignable_v<t>.
seqan3::alphabet_proxy::to_rank
constexpr auto to_rank() const noexcept
Returns the rank.
Definition: alphabet_proxy.hpp:219
seqan3::alphabet_proxy::operator!=
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:291
seqan3::assign_char_to
constexpr auto assign_char_to
Assign a character to an alphabet object.
Definition: concept.hpp:416
seqan3::complement
constexpr auto complement
Return the complement of a nucleotide object.
Definition: concept.hpp:93
std::conditional_t
seqan3::alphabet_proxy::complement
constexpr alphabet_type complement() const noexcept
Returns the complement.
Definition: alphabet_proxy.hpp:243
seqan3::alphabet_proxy::assign_char
constexpr derived_type & assign_char(char_type const c) noexcept
Assigns a character.
Definition: alphabet_proxy.hpp:159
writable_alphabet
Refines seqan3::alphabet and adds assignability.
writable_quality_alphabet
A concept that indicates whether a writable alphabet represents quality scores.
seqan3::alphabet_proxy
A CRTP-base that eases the definition of proxy types returned in place of regular alphabets.
Definition: alphabet_proxy.hpp:59