BioC++ core-0.7.0
The Modern C++ libraries for Bioinformatics.
 
Loading...
Searching...
No Matches
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 <cassert>
17#include <concepts>
18#include <type_traits>
19
22
23namespace bio::alphabet
24{
25
53template <typename derived_type, size_t size, typename char_t = char>
54class base
55{
56protected:
57 static_assert(size != 0, "alphabet size must be >= 1"); // == 1 is handled below in separate specialisation
58
67
70 friend derived_type;
71
73 explicit constexpr base(rank_type r) noexcept : rank{r} {}
74
75public:
79 constexpr base() noexcept = default;
80 constexpr base(base const &) noexcept = default;
81 constexpr base(base &&) noexcept = default;
82 constexpr base & operator=(base const &) noexcept = default;
83 constexpr base & operator=(base &&) noexcept = default;
84 ~base() noexcept = default;
86
104 constexpr char_type to_char() const noexcept
105 requires(!std::same_as<char_t, void>)
106 {
107 return derived_type::rank_to_char[rank];
108 }
109
124 constexpr rank_type to_rank() const noexcept { return rank; }
126
145 constexpr derived_type & assign_char(char_type const c) noexcept
146 requires(!std::same_as<char_t, void>)
147 {
148 using index_t = std::make_unsigned_t<char_type>;
149 rank = derived_type::char_to_rank[static_cast<index_t>(c)];
150 return static_cast<derived_type &>(*this);
151 }
152
168 constexpr derived_type & assign_rank(rank_type const c) noexcept
169 {
170 assert(static_cast<size_t>(c) < static_cast<size_t>(alphabet_size));
171 rank = c;
172 return static_cast<derived_type &>(*this);
173 }
175
177 static constexpr size_t alphabet_size = size;
178
181
183 friend constexpr bool operator==(derived_type const lhs, derived_type const rhs)
184 {
185 return lhs.to_rank() == rhs.to_rank();
186 }
187
189 friend constexpr auto operator<=>(derived_type const lhs, derived_type const rhs)
190 {
191 return lhs.to_rank() <=> rhs.to_rank();
192 }
194
195private:
197 rank_type rank;
198
200 friend constexpr auto tag_invoke(custom::to_rank, derived_type const a) noexcept { return a.to_rank(); }
201
203 friend constexpr derived_type & tag_invoke(custom::assign_rank_to, rank_type const r, derived_type & a) noexcept
204 requires(requires {
205 {
206 a.assign_rank(r)
207 };
208 })
209 {
210 return a.assign_rank(r);
211 }
212
214 friend constexpr auto tag_invoke(custom::to_char, derived_type const a) noexcept
215 requires(requires {
216 {
217 a.to_char()
218 };
219 })
220 {
221 return a.to_char();
222 }
223
225 friend constexpr derived_type & tag_invoke(custom::assign_char_to, char_type const c, derived_type & a) noexcept
226 requires(requires {
227 {
228 a.assign_char(c)
229 };
230 })
231 {
232 return a.assign_char(c);
233 }
234
236 friend constexpr bool tag_invoke(custom::char_is_valid_for, char_type const c, derived_type) noexcept
237 requires(requires {
238 {
239 derived_type::char_is_valid(c)
240 };
241 })
242 {
243 return derived_type::char_is_valid(c);
244 }
245
248 char_type const c,
250 requires(requires {
251 {
252 derived_type::char_is_valid(c)
253 };
255 {
256 return derived_type::char_is_valid(c);
257 }
258
260 friend consteval auto tag_invoke(custom::size, derived_type) noexcept
262 {
263 return size;
264 }
265
269 {
270 return size;
271 }
272};
273
285template <typename derived_type, typename char_t>
286class base<derived_type, 1ul, char_t>
287{
288protected:
295 using rank_type = uint8_t;
297
298public:
302 constexpr base() noexcept = default;
303 constexpr base(base const &) noexcept = default;
304 constexpr base(base &&) noexcept = default;
305 constexpr base & operator=(base const &) noexcept = default;
306 constexpr base & operator=(base &&) noexcept = default;
307 ~base() noexcept = default;
309
314 constexpr char_type to_char() const noexcept
315 requires(!std::same_as<char_t, void>)
316 {
317 return derived_type::char_value;
318 }
319
321 constexpr rank_type to_rank() const noexcept { return 0; }
323
328 constexpr derived_type & assign_char(char_type const) noexcept
329 requires(!std::same_as<char_t, void>)
330 {
331 return static_cast<derived_type &>(*this);
332 }
333
335 constexpr derived_type & assign_rank(rank_type const) noexcept { return static_cast<derived_type &>(*this); }
337
339 static constexpr size_t alphabet_size = 1;
340
343
345 friend constexpr bool operator==(derived_type const, derived_type const) noexcept { return true; }
346
348 friend constexpr bool operator<(derived_type const, derived_type const) noexcept { return false; }
349
351 friend constexpr bool operator>(derived_type const, derived_type const) noexcept { return false; }
352
354 friend constexpr bool operator<=(derived_type const, derived_type const) noexcept { return true; }
355
357 friend constexpr bool operator>=(derived_type const, derived_type const) noexcept { return true; }
359private:
361 friend constexpr rank_type tag_invoke(custom::to_rank, derived_type) noexcept { return 0; }
362
364 friend constexpr derived_type & tag_invoke(custom::assign_rank_to, rank_type const, derived_type & a) noexcept
365 {
366 return a;
367 }
368
370 friend constexpr auto tag_invoke(custom::to_char, derived_type const a) noexcept
371 requires(requires {
372 {
373 a.to_char()
374 };
375 })
376 {
377 return a.to_char();
378 }
379
381 friend constexpr derived_type & tag_invoke(custom::assign_char_to, char_type const c, derived_type & a) noexcept
382 requires(requires {
383 {
384 a.assign_char(c)
385 };
386 })
387 {
388 return a;
389 }
390
392 friend constexpr bool tag_invoke(custom::char_is_valid_for, char_type const c, derived_type) noexcept
393 requires(requires {
394 {
395 derived_type::char_is_valid(c)
396 };
397 } && std::is_nothrow_default_constructible_v<derived_type>)
398 {
399 return derived_type::char_is_valid(c);
400 }
401
404 char_type const c,
406 requires(requires {
407 {
408 derived_type::char_is_valid(c)
409 };
410 } && !std::is_nothrow_default_constructible_v<derived_type>)
411 {
412 return derived_type::char_is_valid(c);
413 }
414
416 friend consteval auto tag_invoke(custom::size, derived_type) noexcept
418 {
419 return alphabet_size;
420 }
421
425 {
426 return alphabet_size;
427 }
428};
429
430} // namespace bio::alphabet
Core alphabet concept and free function/type trait wrappers.
friend constexpr bool operator<=(derived_type const, derived_type const) noexcept
Letters are always equal.
Definition: base.hpp:354
friend constexpr bool tag_invoke(custom::char_is_valid_for, char_type const c, derived_type) noexcept
tag_invoke() wrapper around member.
Definition: base.hpp:392
friend constexpr derived_type & tag_invoke(custom::assign_rank_to, rank_type const, derived_type &a) noexcept
tag_invoke() wrapper around member.
Definition: base.hpp:364
constexpr derived_type & assign_char(char_type const) noexcept
Assign from a character, implicitly converts invalid characters.
Definition: base.hpp:328
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: base.hpp:403
uint8_t rank_type
The type of the alphabet when represented as a number (e.g. via to_rank()).
Definition: base.hpp:295
friend constexpr derived_type & tag_invoke(custom::assign_char_to, char_type const c, derived_type &a) noexcept
tag_invoke() wrapper around member.
Definition: base.hpp:381
friend consteval auto tag_invoke(custom::size, std::type_identity< derived_type >) noexcept
tag_invoke() wrapper around member.
Definition: base.hpp:423
constexpr base() noexcept=default
Defaulted.
constexpr derived_type & assign_rank(rank_type const) noexcept
Assign from a numeric value.
Definition: base.hpp:335
friend constexpr bool operator>=(derived_type const, derived_type const) noexcept
Letters are always equal.
Definition: base.hpp:357
friend constexpr bool operator<(derived_type const, derived_type const) noexcept
One letter cannot be smaller than another.
Definition: base.hpp:348
friend constexpr auto tag_invoke(custom::to_char, derived_type const a) noexcept
tag_invoke() wrapper around member.
Definition: base.hpp:370
friend constexpr bool operator==(derived_type const, derived_type const) noexcept
Letters are always equal.
Definition: base.hpp:345
friend constexpr bool operator>(derived_type const, derived_type const) noexcept
One letter cannot be bigger than another.
Definition: base.hpp:351
friend constexpr rank_type tag_invoke(custom::to_rank, derived_type) noexcept
tag_invoke() wrapper around member.
Definition: base.hpp:361
friend consteval auto tag_invoke(custom::size, derived_type) noexcept
tag_invoke() wrapper around member.
Definition: base.hpp:416
constexpr rank_type to_rank() const noexcept
Return the letter's numeric value (rank in the alphabet).
Definition: base.hpp:321
A CRTP-base that makes defining a custom alphabet easier.
Definition: base.hpp:55
friend constexpr auto operator<=>(derived_type const lhs, derived_type const rhs)
Checks order of lhs and rhs.
Definition: base.hpp:189
friend constexpr bool operator==(derived_type const lhs, derived_type const rhs)
Checks whether the letters lhs and rhs are equal.
Definition: base.hpp:183
constexpr derived_type & assign_rank(rank_type const c) noexcept
Assign from a numeric value.
Definition: base.hpp:168
friend constexpr bool tag_invoke(custom::char_is_valid_for, char_type const c, derived_type) noexcept
tag_invoke() wrapper around member.
Definition: base.hpp:236
friend constexpr derived_type & tag_invoke(custom::assign_char_to, char_type const c, derived_type &a) noexcept
tag_invoke() wrapper around member.
Definition: base.hpp:225
friend consteval auto tag_invoke(custom::size, std::type_identity< derived_type >) noexcept
tag_invoke() wrapper around member.
Definition: base.hpp:267
friend constexpr auto tag_invoke(custom::to_rank, derived_type const a) noexcept
tag_invoke() wrapper around member.
Definition: base.hpp:200
static constexpr size_t alphabet_size
The size of the alphabet, i.e. the number of different values it can take.
Definition: base.hpp:177
constexpr char_type to_char() const noexcept
Return the letter as a character of char_type.
Definition: base.hpp:104
meta::detail::min_viable_uint_t< size - 1 > rank_type
The type of the alphabet when represented as a number (e.g. via to_rank()).
Definition: base.hpp:65
constexpr derived_type & assign_char(char_type const c) noexcept
Assign from a character, implicitly converts invalid characters.
Definition: base.hpp:145
constexpr base() noexcept=default
Defaulted.
friend constexpr auto tag_invoke(custom::to_char, derived_type const a) noexcept
tag_invoke() wrapper around member.
Definition: base.hpp:214
friend constexpr derived_type & tag_invoke(custom::assign_rank_to, rank_type const r, derived_type &a) noexcept
tag_invoke() wrapper around member.
Definition: base.hpp:203
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: base.hpp:247
friend consteval auto tag_invoke(custom::size, derived_type) noexcept
tag_invoke() wrapper around member.
Definition: base.hpp:260
constexpr rank_type to_rank() const noexcept
Return the letter's numeric value (rank in the alphabet).
Definition: base.hpp:124
A type that is std::default_initializable<t> at compile-time.
Definition: core_language.hpp:143
constexpr auto size
A type trait that holds the size of a (semi-)alphabet.
Definition: concept.hpp:517
decltype(bio::alphabet::to_char(std::declval< alphabet_type const >())) char_t
The char_type of the alphabet; defined as the return type of bio::alphabet::to_char.
Definition: concept.hpp:212
Provides metaprogramming utilities for integer types.
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_rank_to.#.
Definition: tag.hpp:29
Customisation tag for bio::alphabet::assign_char_to.
Definition: tag.hpp:41
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::to_rank.
Definition: tag.hpp:25