BioC++ core-0.7.0
The Modern C++ libraries for Bioinformatics.
 
Loading...
Searching...
No Matches
proxy_base.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2022 deCODE Genetics
3// Copyright (c) 2006-2020, Knut Reinert & Freie Universität Berlin
4// Copyright (c) 2016-2020, Knut Reinert & MPI für molekulare Genetik
5// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
6// shipped with this file and also available at: https://github.com/biocpp/biocpp-core/blob/main/LICENSE.md
7// -----------------------------------------------------------------------------------------------------
8
14#pragma once
15
16#include <concepts>
17
18#include <bio/alphabet/base.hpp>
24
25namespace bio::alphabet
26{
27
60template <typename derived_type, writable_semialphabet alphabet_type>
61 requires std::regular<alphabet_type>
63{
64private:
67
70
71private:
75 constexpr proxy_base() noexcept = default;
76 constexpr proxy_base(proxy_base const &) = default;
77 constexpr proxy_base(proxy_base &&) noexcept = default;
78 constexpr proxy_base & operator=(proxy_base const &) = delete;
79 constexpr proxy_base & operator=(proxy_base &&) noexcept = delete;
80 ~proxy_base() = default;
81
83 constexpr derived_type & operator=(derived_type const & c) noexcept
84 {
85 static_cast<derived_type &>(*this).assign_rank(c.to_rank()); // <- this invokes the actual proxy
86 return static_cast<derived_type &>(*this);
87 }
88
90 constexpr derived_type const & operator=(derived_type const & c) const noexcept
91 {
92 static_cast<derived_type const &>(*this).assign_rank(c.to_rank()); // <- this invokes the actual proxy
93 return static_cast<derived_type const &>(*this);
94 }
95
97 constexpr derived_type & operator=(alphabet_type const & c) noexcept
98 {
99 static_cast<derived_type &>(*this).assign_rank(bio::alphabet::to_rank(c)); // <- this invokes the actual proxy
100 return static_cast<derived_type &>(*this);
101 }
102
104 constexpr derived_type const & operator=(alphabet_type const & c) const noexcept
105 {
106 static_cast<derived_type const &>(*this).assign_rank(
107 bio::alphabet::to_rank(c)); // <- this invokes the actual proxy
108 return static_cast<derived_type const &>(*this);
109 }
110
112 template <typename indirect_assignable_type>
113 constexpr derived_type & operator=(indirect_assignable_type const & c) const noexcept
115 {
116 alphabet_type a;
117 a = c;
118 return operator=(a);
119 }
121
123 friend derived_type;
124
125public:
127 static constexpr auto alphabet_size = bio::alphabet::size<alphabet_type>;
128
135 constexpr derived_type & assign_char(char_type const c) noexcept
137 {
138 alphabet_type tmp;
139 assign_char_to(c, tmp);
140 return operator=(tmp);
141 }
142
144 constexpr derived_type const & assign_char(char_type const c) const noexcept
146 {
147 alphabet_type tmp;
148 assign_char_to(c, tmp);
149 return operator=(tmp);
150 }
151
153 constexpr derived_type & assign_phred(phred_type const c) noexcept
155 {
156 alphabet_type tmp;
157 assign_phred_to(c, tmp);
158 return operator=(tmp);
159 }
160
162 constexpr derived_type const & assign_phred(phred_type const c) const noexcept
164 {
165 alphabet_type tmp;
166 assign_phred_to(c, tmp);
167 return operator=(tmp);
168 }
170
176 constexpr operator alphabet_type() const noexcept
177 {
178 return alphabet::assign_rank_to(static_cast<derived_type const &>(*this).to_rank(), alphabet_type{});
179
180 /* Instead of static_cast'ing to the alphabet_type which also considers the constructors of the alphabet_type,
181 * we explicitly invoke this operator in various places.
182 * This prevents errors associated with using alphabet_type's constructors.
183 *
184 * This is one of error cases:
185 * The tuple composite bio::alphabet::qualified returns a component_proxy which inherits from proxy_base_base.
186 * The qualified alphabet itself inherits from quality_base.
187 * Now when accessing get<1>(seq_qual_alph) we want to call to_phred at some point because we want the quality,
188 * therefore the to_phred function from proxy_base is called, but this function did a static_cast to the
189 * derived type which is calling the constructor from quality_base. Unfortunately now, the generic quality_base
190 * constructor uses `assign_phred_to(to_phred(other), static_cast<derived_type &>(*this))`; (here) which again
191 * tries to call to_phred of the proxy_base => infinite loop :boom:
192 */
193 }
194
196 template <typename other_t>
197 requires(std::convertible_to<alphabet_type, other_t>)
198 constexpr operator other_t() const noexcept
199 {
200 return operator alphabet_type();
201 }
202
204 constexpr auto to_char() const noexcept
205 requires alphabet<alphabet_type>
206 {
207 return bio::alphabet::to_char(operator alphabet_type());
208 }
209
211 constexpr auto to_phred() const noexcept
212 requires quality<alphabet_type>
213 {
214 return bio::alphabet::to_phred(operator alphabet_type());
215 }
216
218 constexpr alphabet_type complement() const noexcept
219 requires nucleotide<alphabet_type>
220 {
221 return bio::alphabet::complement(operator alphabet_type());
222 }
223
225 static constexpr bool char_is_valid(char_type const c) noexcept
227 {
228 return char_is_valid_for<alphabet_type>(c);
229 }
231
233 friend constexpr void swap(derived_type const & lhs, derived_type const & rhs)
234 {
235 alphabet_type lhs_value = lhs.operator alphabet_type();
236 alphabet_type rhs_value = rhs.operator alphabet_type();
237 lhs = rhs_value;
238 rhs = lhs_value;
239 }
240
242 friend constexpr void swap(derived_type & lhs, derived_type & rhs)
243 {
244 alphabet_type lhs_value = lhs.operator alphabet_type();
245 alphabet_type rhs_value = rhs.operator alphabet_type();
246 lhs = rhs_value;
247 rhs = lhs_value;
248 }
249
256 friend constexpr bool operator==(derived_type const lhs, derived_type const rhs)
257 {
258 return lhs.to_rank() == rhs.to_rank();
259 }
260
262 friend constexpr auto operator<=>(derived_type const lhs, derived_type const rhs)
263 {
264 return lhs.to_rank() <=> rhs.to_rank();
265 }
266
268 template <meta::different_from<derived_type> t>
270 friend constexpr bool operator==(derived_type const lhs, t const rhs) noexcept
271 {
272 return (lhs.operator alphabet_type() == rhs);
273 }
274
276 template <meta::different_from<derived_type> t>
278 friend constexpr bool operator==(t const lhs, derived_type const rhs) noexcept
279 {
280 return (rhs == lhs);
281 }
283
284private:
286 friend constexpr auto tag_invoke(custom::to_rank, derived_type const a) noexcept { return a.to_rank(); }
287
289 friend constexpr derived_type & tag_invoke(custom::assign_rank_to, auto const r, derived_type & a) noexcept
290 requires(requires {
291 {
292 a.assign_rank(r)
293 };
294 })
295 {
296 return a.assign_rank(r);
297 }
298
300 friend constexpr derived_type const & tag_invoke(custom::assign_rank_to,
301 auto const r,
302 derived_type const & a) noexcept
303 requires(requires {
304 {
305 a.assign_rank(r)
306 };
307 })
308 {
309 return a.assign_rank(r);
310 }
311
313 friend constexpr auto tag_invoke(custom::to_char, derived_type const a) noexcept
314 requires(requires {
315 {
316 a.to_char()
317 };
318 })
319 {
320 return a.to_char();
321 }
322
324 friend constexpr derived_type & tag_invoke(custom::assign_char_to, char_type const c, derived_type & a) noexcept
325 requires(requires {
326 {
327 a.assign_char(c)
328 };
329 })
330 {
331 return a.assign_char(c);
332 }
333
335 friend constexpr derived_type const & tag_invoke(custom::assign_char_to,
336 char_type const c,
337 derived_type const & a) noexcept
338 requires(requires {
339 {
340 a.assign_char(c)
341 };
342 })
343 {
344 return a.assign_char(c);
345 }
346
348 friend constexpr bool tag_invoke(custom::char_is_valid_for, char_type const c, derived_type) noexcept
349 requires(requires {
350 {
351 derived_type::char_is_valid(c)
352 };
353 })
354 {
355 return derived_type::char_is_valid(c);
356 }
357
360 char_type const c,
362 requires(requires {
363 {
364 derived_type::char_is_valid(c)
365 };
367 {
368 return derived_type::char_is_valid(c);
369 }
370
372 friend consteval auto tag_invoke(custom::size, derived_type) noexcept
374 {
375 return alphabet_size;
376 }
377
381 {
382 return alphabet_size;
383 }
384
386 friend constexpr auto tag_invoke(custom::complement, derived_type const a) noexcept
387 requires(requires {
388 {
389 a.complement()
390 };
391 })
392 {
393 return a.complement();
394 }
395
397 friend constexpr phred_type tag_invoke(custom::to_phred, derived_type const a) noexcept
398 requires(requires {
399 {
400 a.to_phred()
401 };
402 })
403 {
404 return a.to_phred();
405 }
406
408 friend constexpr derived_type & tag_invoke(custom::assign_phred_to, phred_type const p, derived_type & a) noexcept
409 requires(requires {
410 {
411 a.assign_phred(p)
412 };
413 })
414 {
415 return a.assign_phred(p);
416 }
417
419 friend constexpr derived_type const & tag_invoke(custom::assign_phred_to,
420 phred_type const p,
421 derived_type const & a) noexcept
422 requires(requires {
423 {
424 a.assign_phred(p)
425 };
426 })
427 {
428 return a.assign_phred(p);
429 }
430};
431
432} // namespace bio::alphabet
Provides bio::alphabet::nucleotide.
Quality alphabet concept.
Provides bio::alphabet::base.
Provides various type traits on generic types.
A CRTP-base that eases the definition of proxy types returned in place of regular alphabets.
Definition: proxy_base.hpp:63
constexpr derived_type & assign_phred(phred_type const c) noexcept
Assign from the numeric phred value.
Definition: proxy_base.hpp:153
constexpr derived_type const & assign_phred(phred_type const c) const noexcept
Assign from the numeric phred value.
Definition: proxy_base.hpp:162
friend constexpr auto operator<=>(derived_type const lhs, derived_type const rhs)
Checks order of lhs and rhs.
Definition: proxy_base.hpp:262
friend constexpr derived_type & tag_invoke(custom::assign_phred_to, phred_type const p, derived_type &a) noexcept
tag_invoke() wrapper around member.
Definition: proxy_base.hpp:408
friend constexpr derived_type const & tag_invoke(custom::assign_char_to, char_type const c, derived_type const &a) noexcept
tag_invoke() wrapper around member.
Definition: proxy_base.hpp:335
static constexpr auto alphabet_size
The alphabet size.
Definition: proxy_base.hpp:127
friend constexpr bool operator==(derived_type const lhs, derived_type const rhs)
Checks whether the letters lhs and rhs are equal.
Definition: proxy_base.hpp:256
friend constexpr phred_type tag_invoke(custom::to_phred, derived_type const a) noexcept
tag_invoke() wrapper around member.
Definition: proxy_base.hpp:397
friend constexpr bool tag_invoke(custom::char_is_valid_for, char_type const c, derived_type) noexcept
tag_invoke() wrapper around member.
Definition: proxy_base.hpp:348
constexpr auto to_phred() const noexcept
Return the alphabet's value in phred representation.
Definition: proxy_base.hpp:211
friend constexpr derived_type & tag_invoke(custom::assign_rank_to, auto const r, derived_type &a) noexcept
tag_invoke() wrapper around member.
Definition: proxy_base.hpp:289
friend constexpr derived_type const & tag_invoke(custom::assign_rank_to, auto const r, derived_type const &a) noexcept
tag_invoke() wrapper around member.
Definition: proxy_base.hpp:300
friend constexpr derived_type & tag_invoke(custom::assign_char_to, char_type const c, derived_type &a) noexcept
tag_invoke() wrapper around member.
Definition: proxy_base.hpp:324
friend consteval auto tag_invoke(custom::size, std::type_identity< derived_type >) noexcept
tag_invoke() wrapper around member.
Definition: proxy_base.hpp:379
constexpr derived_type & assign_char(char_type const c) noexcept
Assign from a character, implicitly converts invalid characters.
Definition: proxy_base.hpp:135
friend constexpr auto tag_invoke(custom::to_rank, derived_type const a) noexcept
tag_invoke() wrapper around member.
Definition: proxy_base.hpp:286
static constexpr bool char_is_valid(char_type const c) noexcept
Delegate to the emulated type's validator.
Definition: proxy_base.hpp:225
constexpr alphabet_type complement() const noexcept
Return the complement of the letter.
Definition: proxy_base.hpp:218
friend constexpr auto tag_invoke(custom::complement, derived_type const a) noexcept
tag_invoke() wrapper around member.
Definition: proxy_base.hpp:386
friend constexpr void swap(derived_type const &lhs, derived_type const &rhs)
Checks order of lhs and rhs.
Definition: proxy_base.hpp:233
friend constexpr auto tag_invoke(custom::to_char, derived_type const a) noexcept
tag_invoke() wrapper around member.
Definition: proxy_base.hpp:313
friend constexpr void swap(derived_type &lhs, derived_type &rhs)
Checks order of lhs and rhs.
Definition: proxy_base.hpp:242
friend constexpr bool tag_invoke(custom::char_is_valid_for, char_type const c, std::type_identity< derived_type >) noexcept
tag_invoke() wrapper around member.
Definition: proxy_base.hpp:359
constexpr derived_type const & assign_char(char_type const c) const noexcept
Assign from a character, implicitly converts invalid characters.
Definition: proxy_base.hpp:144
constexpr auto to_char() const noexcept
Return the letter as a character of char_type.
Definition: proxy_base.hpp:204
friend consteval auto tag_invoke(custom::size, derived_type) noexcept
tag_invoke() wrapper around member.
Definition: proxy_base.hpp:372
friend constexpr derived_type const & tag_invoke(custom::assign_phred_to, phred_type const p, derived_type const &a) noexcept
tag_invoke() wrapper around member.
Definition: proxy_base.hpp:419
The generic alphabet concept that covers most data types used in ranges.
Definition: concept.hpp:643
A concept that indicates whether an alphabet represents nucleotides.
Definition: concept.hpp:113
A concept that indicates whether an alphabet represents quality scores.
Definition: concept.hpp:171
Refines bio::alphabet::alphabet and adds assignability.
Definition: concept.hpp:688
A concept that indicates whether a writable alphabet represents quality scores.
Definition: concept.hpp:208
A type that is std::default_initializable<t> at compile-time.
Definition: core_language.hpp:143
Resolves to std::is_assignable_v<t>.
Definition: core_language.hpp:128
Requires the two operands to be comparable with == and != in both directions.
Definition: core_language.hpp:33
Provides concepts for core language types and relations that don't have concepts in C++20 (yet).
constexpr auto to_char
Return the char representation of an alphabet object.
Definition: concept.hpp:192
constexpr auto assign_char_to
Assign a char to an alphabet object.
Definition: concept.hpp:260
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:70
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition: concept.hpp:138
constexpr auto complement
Return the complement of a nucleotide object.
Definition: concept.hpp:68
constexpr auto assign_phred_to
Assign a phred score to a quality alphabet object.
Definition: concept.hpp:128
constexpr auto to_phred
The public getter function for the phred representation of a quality score.
Definition: concept.hpp:65
typename valid_template_spec_or< fallback_t, templ_t, spec_t... >::type valid_template_spec_or_t
Helper for bio::meta::valid_template_spec_or (transformation_trait shortcut).
Definition: template_inspection.hpp:244
The alphabet module's namespace.
Definition: aa10li.hpp:23
Customisation tag for bio::alphabet::assign_char_to.
Definition: tag.hpp:37
Customisation tag for bio::alphabet::assign_char_to.
Definition: tag.hpp:57
Customisation tag for bio::alphabet::assign_rank_to.#.
Definition: tag.hpp:29
Customisation tag for bio::alphabet::assign_char_to.
Definition: tag.hpp:41
Customisation tag for bio::alphabet::complement.
Definition: tag.hpp:49
CPO tag definition for bio::alphabet::size.
Definition: tag.hpp:45
Customisation tag for bio::alphabet::to_char.
Definition: tag.hpp:33
Customisation tag for bio::alphabet::assign_char_to.
Definition: tag.hpp:53
Customisation tag for bio::alphabet::to_rank.
Definition: tag.hpp:25
Provides various traits to inspect templates.