SeqAn3  3.0.0
The Modern C++ library for sequence analysis.
alphabet_proxy.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 
15 #pragma once
16 
23 #include <seqan3/std/concepts>
24 
25 #if 0 // this is the alphabet_proxy I want, but GCC won't give me:
27 
28 template <typename derived_type, typename alphabet_type>
29 class alphabet_proxy : public alphabet_type
30 {
31 public:
32  using base_t = alphabet_type;
33 
35  using typename base_t::rank_type;
36  using char_type = detail::transformation_trait_or_t<std::type_identity<alphabet_char_t<<alphabet_type>, void>;
37  using phred_type = detail::transformation_trait_or_t<alphabet_phred_t<alphabet_type>, void>;
38 
39  using char_type_virtual = detail::valid_template_spec_or_t<char, alphabet_char_t, alphabet_type>;
40  using phred_type_virtual = detail::valid_template_spec_or_t<int8_t, alphabet_phred_t, alphabet_type>;
41 
42  constexpr alphabet_proxy() : base_t{} {}
43  constexpr alphabet_proxy(alphabet_proxy const &) = default;
44  constexpr alphabet_proxy(alphabet_proxy &&) = default;
45  constexpr alphabet_proxy & operator=(alphabet_proxy const &) = default;
46  constexpr alphabet_proxy & operator=(alphabet_proxy &&) = default;
47  ~alphabet_proxy() = default;
48 
49  constexpr alphabet_proxy(alphabet_type const a) :
50  base_t{a}
51  {}
52 
53  constexpr alphabet_proxy & operator=(alphabet_type const & c) noexcept
54  {
55  base_t::assign_rank(seqan3::to_rank(c));
56  static_cast<derived_type &>(*this).on_update(); // <- this invokes the actual proxy behaviour!
57  return *this;
58  }
59 
60  template <typename indirect_assignable_type>
62  constexpr alphabet_proxy & operator=(indirect_assignable_type const & c) noexcept
63  {
64  alphabet_type a{};
65  a = c;
66  return operator=(a);
67  }
68 
69  constexpr alphabet_proxy & assign_char(char_type_virtual const c) noexcept
71  {
72  alphabet_type tmp{};
74  assign_char_to(c, tmp);
75  return operator=(tmp);
76  }
77 
78  constexpr alphabet_proxy & assign_rank(alphabet_rank_t<alphabet_type> const r) noexcept
79  {
80  alphabet_type tmp{};
82  assign_rank_to(r, tmp);
83  return operator=(tmp);
84  }
85 
86  constexpr alphabet_proxy & assign_phred(phred_type_virtual const c) noexcept
88  {
89  alphabet_type tmp{};
90  assign_phred_to(c, tmp);
91  return operator=(tmp);
92  }
93 };
94 #endif
95 
96 #if 1// this is the one that works for most things, but not all
97 
98 namespace seqan3
99 {
100 
130 template <typename derived_type, WritableSemialphabet alphabet_type>
131 class alphabet_proxy : public alphabet_base<derived_type,
132  alphabet_size<alphabet_type>,
133  detail::valid_template_spec_or_t<void, alphabet_char_t, alphabet_type>>
134 {
135 private:
137  using base_t = alphabet_base<derived_type,
138  alphabet_size<alphabet_type>,
139  detail::valid_template_spec_or_t<void, alphabet_char_t, alphabet_type>>;
140 
142  friend base_t;
143 
145  using char_type = detail::valid_template_spec_or_t<char, alphabet_char_t, alphabet_type>;
146 
148  using phred_type = detail::valid_template_spec_or_t<int8_t, alphabet_phred_t, alphabet_type>;
149 
150 public:
151  // Import from base:
152  using base_t::alphabet_size;
153  using base_t::to_rank;
154 
162 
163 private:
165 
169  constexpr alphabet_proxy() noexcept : base_t{} {}
170  constexpr alphabet_proxy(alphabet_proxy const &) = default;
171  constexpr alphabet_proxy(alphabet_proxy &&) = default;
172  constexpr alphabet_proxy & operator=(alphabet_proxy const &) = default;
173  constexpr alphabet_proxy & operator=(alphabet_proxy &&) = default;
174  ~alphabet_proxy() = default;
175 
177  constexpr alphabet_proxy(alphabet_type const a) noexcept
178  {
180  }
181 
183  constexpr derived_type & operator=(alphabet_type const & c) noexcept
184  {
186  static_cast<derived_type &>(*this).on_update(); // <- this invokes the actual proxy behaviour!
187  return static_cast<derived_type &>(*this);
188  }
189 
191  template <typename indirect_assignable_type>
192  constexpr derived_type & operator=(indirect_assignable_type const & c) noexcept
194  {
195  alphabet_type a{};
196  a = c;
197  return operator=(a);
198  }
200 
202  friend derived_type;
203 
204 public:
210  constexpr derived_type & assign_rank(alphabet_rank_t<alphabet_type> const r) noexcept
211  {
212  alphabet_type tmp{};
213  assign_rank_to(r, tmp);
214  return operator=(tmp);
215  }
216 
217  constexpr derived_type & assign_char(char_type const c) noexcept
219  {
220  alphabet_type tmp{};
221  assign_char_to(c, tmp);
222  return operator=(tmp);
223  }
224 
225  constexpr derived_type & assign_phred(phred_type const c) noexcept
226  requires WritableQualityAlphabet<alphabet_type>
227  {
228  alphabet_type tmp{};
229  assign_phred_to(c, tmp);
230  return operator=(tmp);
231  }
233 
238  constexpr operator alphabet_type() const noexcept
240  {
241  return assign_rank_to(to_rank(), alphabet_type{});
242  }
243 
244  constexpr auto to_char() const noexcept
245  requires Alphabet<alphabet_type>
246  {
247  /* (smehringer) Explicit conversion instead of static_cast:
248  * See explanation in to_phred().
249  */
250  return seqan3::to_char(operator alphabet_type());
251  }
252 
253  constexpr auto to_phred() const noexcept
255  {
256  using seqan3::to_phred;
257  /* (smehringer) Explicit conversion instead of static_cast:
258  * The tuple composite qualified returns a component_proxy which inherits from alphabet_proxy_base.
259  * The qualified alphabet itself inherits from quality_base.
260  * Now when accessing get<1>(seq_qual_alph) we want to call to_phred at some point because we want the quality,
261  * therefore the to_phred function from alphabet_proxy is called, but this function did a static_cast to the
262  * derived type which is calling the constructor from quality_base. Unfortunately now, the generic quality_base
263  * constructor uses `assign_phred_to(to_phred(other), static_cast<derived_type &>(*this))`; (here) which again
264  * tries to call to_phred of the alphabet_proxy => infinite loop :boom:
265  */
266  return to_phred(operator alphabet_type());
267  }
268 
269 #if 0 // this currently causes GCC ICE in alphabet_tuple_base test
270  constexpr alphabet_type complement() const noexcept
272  {
273  using seqan3::complement;
274  return complement(static_cast<alphabet_type>(*this));
275  }
276 #endif
277 
279  static constexpr bool char_is_valid(char_type const c) noexcept
281  {
282  return char_is_valid_for<alphabet_type>(c);
283  }
285 };
286 
287 #endif
288 } // namespace seqan3
The generic alphabet concept that covers most data types used in ranges.
Provides concepts for core language types and relations that don&#39;t have concepts in C++20 (yet)...
constexpr auto complement
Return the complement of a nucleotide object.
Definition: concept.hpp:104
The concept std::Assignable<LHS, RHS> specifies that an expression of the type and value category spe...
alphabet_rank_t< alphabet_type > rank_type
The type of the rank representation.
Definition: alphabet_proxy.hpp:160
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
A concept that indicates whether an alphabet represents quality scores.
constexpr auto to_char
Return the char representation of an alphabet object.
Definition: concept.hpp:285
Provides seqan3::detail::transformation_trait_or.
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:103
Provides seqan3::type_list and auxiliary type traits.
The main SeqAn3 namespace.
constexpr derived_type & assign_rank(rank_type const c) noexcept
Assign from a numeric value.
Definition: alphabet_base.hpp:166
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:112
constexpr auto assign_phred_to
Assign a phred score to a quality alphabet object.
Definition: concept.hpp:201
Provides seqan3::NucleotideAlphabet.
The Concepts library.
Refines seqan3::Alphabet and adds assignability.
static constexpr bool char_is_valid(char_type const c) noexcept requires WritableAlphabet< alphabet_type >
Delegate to the emulated type&#39;s validator.
Definition: alphabet_proxy.hpp:279
Provides seqan3::alphabet_base.
constexpr auto to_phred
The public getter function for the phred representation of a quality score.
Definition: concept.hpp:104
static detail::min_viable_uint_t< size > constexpr alphabet_size
The size of the alphabet, i.e. the number of different values it can take.
Definition: alphabet_base.hpp:175
A concept that indicates whether an alphabet represents nucleotides.
Provides various type traits on generic types.
constexpr rank_type to_rank() const noexcept
Return the letter&#39;s numeric value (rank in the alphabet).
Definition: alphabet_base.hpp:117
A CRTP-base that makes defining a custom alphabet easier.
Definition: alphabet_base.hpp:52
constexpr auto assign_char_to
Assign a character to an alphabet object.
Definition: concept.hpp:395
Quality alphabet concept.
The concept std::Same<T, U> is satisfied if and only if T and U denote the same type.
constexpr auto alphabet_size
A type trait that holds the size of a (semi-)alphabet.
Definition: concept.hpp:678
Resolves to std::is_assignable_v<t>.