BioC++ core-0.7.0
The Modern C++ libraries for Bioinformatics.
 
Loading...
Searching...
No Matches
concept.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 <type_traits>
17
20#include <bio/core.hpp>
25
26// ============================================================================
27// to_rank()
28// ============================================================================
29
30namespace bio::alphabet
31{
32
70inline constexpr auto to_rank = []<typename alph_t>(alph_t const a) noexcept
71 requires(requires {
72 {
73 tag_invoke(custom::to_rank{}, a)
74 } -> std::integral;
75 requires noexcept(tag_invoke(custom::to_rank{}, a));
76 })
77{
78 return tag_invoke(custom::to_rank{}, a);
79};
81
84template <typename semi_alphabet_type>
85 requires(requires {
86 {
87 bio::alphabet::to_rank(std::declval<semi_alphabet_type>())
88 };
89 })
90using rank_t = decltype(bio::alphabet::to_rank(std::declval<semi_alphabet_type>()));
91
92// ============================================================================
93// assign_rank_to()
94// ============================================================================
95
138inline constexpr auto assign_rank_to =
139 []<typename alph_t>(bio::alphabet::rank_t<alph_t> const r, alph_t && a) noexcept -> alph_t
140 requires(requires {
141 {
142 tag_invoke(custom::assign_rank_to{}, r, a)
143 } -> std::same_as<alph_t &>;
144 requires noexcept(tag_invoke(custom::assign_rank_to{}, r, a));
145 })
146{
147 return tag_invoke(custom::assign_rank_to{}, r, a);
148};
150
151// ============================================================================
152// to_char()
153// ============================================================================
154
192inline constexpr auto to_char = []<typename alph_t>(alph_t const a) noexcept
193 requires(requires {
194 {
195 tag_invoke(custom::to_char{}, a)
196 } -> std::integral;
197 requires noexcept(tag_invoke(custom::to_char{}, a));
198 })
199{
200 return tag_invoke(custom::to_char{}, a);
201};
203
206template <typename alphabet_type>
207 requires(requires(alphabet_type const a) {
208 {
210 };
211 })
212using char_t = decltype(bio::alphabet::to_char(std::declval<alphabet_type const>()));
213
214// ============================================================================
215// assign_char_to()
216// ============================================================================
217
260inline constexpr auto assign_char_to =
261 []<typename alph_t>(bio::alphabet::char_t<alph_t> const c, alph_t && a) noexcept -> alph_t
262 requires(requires {
263 {
264 tag_invoke(custom::assign_char_to{}, c, a)
265 } -> std::same_as<alph_t &>;
266 requires noexcept(tag_invoke(custom::assign_char_to{}, c, a));
267 })
268{
269 return tag_invoke(custom::assign_char_to{}, c, a);
270};
272} // namespace bio::alphabet
273
274// ============================================================================
275// char_is_valid_for()
276// ============================================================================
277
278namespace bio::alphabet::detail
279{
280
283template <typename alph_t>
284struct char_is_valid_for_fn
285{
287 template <typename alph2_t>
288 static constexpr bool impl(char_t<alph2_t> const chr, meta::priority_tag<0>) noexcept
289 requires std::is_nothrow_default_constructible_v<alph2_t>
290 {
291 return to_char(assign_char_to(chr, alph2_t{})) == chr;
292 }
293
295 template <typename alph2_t, typename wrap_t = meta::default_initialisable_wrap_t<alph2_t>>
296 requires(requires(char_t<alph2_t> const c) {
297 {
298 tag_invoke(std::declval<custom::char_is_valid_for>(), c, wrap_t{})
299 } -> std::same_as<bool>;
300 requires noexcept(tag_invoke(std::declval<custom::char_is_valid_for>(), c, wrap_t{}));
301 })
302 static constexpr bool impl(char_t<alph2_t> const chr, meta::priority_tag<1>) noexcept
303 {
304 return tag_invoke(custom::char_is_valid_for{}, chr, wrap_t{});
305 }
306
308 constexpr auto operator()(char_t<alph_t> const chr) const noexcept
309 -> decltype(impl<std::remove_cvref_t<alph_t>>(chr, meta::priority_tag<1>{}))
310 {
311 return impl<std::remove_cvref_t<alph_t>>(chr, meta::priority_tag<1>{});
312 }
313};
314
315} // namespace bio::alphabet::detail
316
317namespace bio::alphabet
318{
319
389template <typename alph_t>
390 requires(requires(char_t<alph_t> a) {
391 {
392 detail::char_is_valid_for_fn<alph_t>{}(a)
393 };
394 })
395inline constexpr auto char_is_valid_for = detail::char_is_valid_for_fn<alph_t>{};
396
398
399} // namespace bio::alphabet
400
401// ============================================================================
402// assign_char_strictly_to()
403// ============================================================================
404
405namespace bio::alphabet::detail
406{
407
410struct assign_char_strictly_to_fn
411{
413 template <typename alph_t>
414 requires(requires(alph_t a, bio::alphabet::char_t<alph_t> r) {
415 {
417 };
418 {
419 bio::alphabet::char_is_valid_for<alph_t>(r)
420 };
421 })
422 auto operator()(bio::alphabet::char_t<alph_t> const r, alph_t && a) const -> alph_t
423 {
424 if (!bio::alphabet::char_is_valid_for<alph_t>(r))
425 throw bio::alphabet::invalid_char_assignment{meta::detail::type_name_as_string<alph_t>, r};
426
428 }
429};
430
431} // namespace bio::alphabet::detail
432
433namespace bio::alphabet
434{
435
461inline constexpr auto assign_char_strictly_to = detail::assign_char_strictly_to_fn{};
463
464// ============================================================================
465// size
466// ============================================================================
467
510template <typename alph_t, typename wrap_t = meta::default_initialisable_wrap_t<alph_t>>
511 requires(requires {
512 {
513 tag_invoke(custom::size{}, wrap_t{})
514 } -> std::integral;
515 requires BIOCPP_IS_CONSTEXPR(tag_invoke(custom::size{}, wrap_t{}));
516 })
517inline constexpr auto size = tag_invoke(custom::size{}, wrap_t{});
518
519// ============================================================================
520// semialphabet
521// ============================================================================
522
561template <typename t>
563 std::totally_ordered<t> && std::copy_constructible<t> && std::is_nothrow_copy_constructible_v<t> && requires(t v) {
564 {
565 bio::alphabet::size<t>
566 };
567 {
569 };
570 };
571
572// ============================================================================
573// writable_semialphabet
574// ============================================================================
575
607template <typename t>
608concept writable_semialphabet = semialphabet<t> && requires(t v, rank_t<t> r) {
609 {
611 };
612};
613
614// ============================================================================
615// alphabet
616// ============================================================================
617
642template <typename t>
643concept alphabet = semialphabet<t> && requires(t v) {
644 {
646 };
647};
648
649// ============================================================================
650// writable_alphabet
651// ============================================================================
652
687template <typename t>
688concept writable_alphabet = alphabet<t> && writable_semialphabet<t> && requires(t v, char_t<t> c) {
689 {
691 };
692
693 {
694 bio::alphabet::char_is_valid_for<t>(c)
695 };
696};
697
698} // namespace bio::alphabet
699// ============================================================================
700// serialisation
701// ============================================================================
702
703#if __has_include(<cereal/details/traits.hpp>)
704# include <cereal/details/traits.hpp>
705#endif
706
707namespace bio::alphabet::detail
708{
709
714#if __has_include(<cereal/details/traits.hpp>)
715template <typename type>
716using strip_cereal_wrapper_t = typename cereal::traits::strip_minimal<std::decay_t<type>>::type;
717#else
718template <typename type>
719using strip_cereal_wrapper_t = type;
720#endif
721
722} // namespace bio::alphabet::detail
723
724namespace bio::alphabet
725{
726
746template <typename archive_t, semialphabet alphabet_t>
747rank_t<alphabet_t> save_minimal(archive_t const &, alphabet_t const & l)
748{
749 return to_rank(l);
750}
751
765template <typename archive_t, typename wrapped_alphabet_t>
766void load_minimal(archive_t const &,
767 wrapped_alphabet_t && l,
768 rank_t<detail::strip_cereal_wrapper_t<wrapped_alphabet_t>> const & r)
769 requires semialphabet<detail::strip_cereal_wrapper_t<wrapped_alphabet_t>>
770{
771 assign_rank_to(r, static_cast<detail::strip_cereal_wrapper_t<wrapped_alphabet_t> &>(l));
772}
777} // namespace bio::alphabet
778
779namespace bio::alphabet::detail
780{
781// ============================================================================
782// constexpr_semialphabet
783// ============================================================================
784
792template <typename t>
793concept constexpr_semialphabet = semialphabet<t> && requires {
794 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
796};
797
798// ============================================================================
799// writable_constexpr_semialphabet
800// ============================================================================
801
810template <typename t>
811concept writable_constexpr_semialphabet = constexpr_semialphabet<t> && writable_semialphabet<t> && requires {
812// currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
813#if BIOCPP_WORKAROUND_CLANG_58078
814 requires true;
815#else
817#endif
818};
819
820// ============================================================================
821// constexpr_alphabet
822// ============================================================================
823
832template <typename t>
833concept constexpr_alphabet = constexpr_semialphabet<t> && alphabet<t> && requires {
834 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
836};
837
838// ============================================================================
839// writable_constexpr_alphabet
840// ============================================================================
841
852template <typename t>
853concept writable_constexpr_alphabet =
854 constexpr_alphabet<t> && writable_constexpr_semialphabet<t> && writable_alphabet<t> && requires {
855// currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
856#if !BIOCPP_WORKAROUND_CLANG_58078
858#endif
859 requires BIOCPP_IS_CONSTEXPR(bio::alphabet::char_is_valid_for<t>(char_t<t>{}));
860 };
861
862} // namespace bio::alphabet::detail
Provides various type traits on generic types.
The generic alphabet concept that covers most data types used in ranges.
Definition: concept.hpp:643
The basis for bio::alphabet::alphabet, but requires only rank interface (not char).
Definition: concept.hpp:562
Refines bio::alphabet::alphabet and adds assignability.
Definition: concept.hpp:688
A refinement of bio::alphabet::semialphabet that adds assignability.
Definition: concept.hpp:608
Provides platform and dependency checks.
Provides concepts for core language types and relations that don't have concepts in C++20 (yet).
Exceptions thrown by entities in the alphabet module.
consteval auto tag_invoke(size, char_type const) noexcept
The number of values the char type can take (e.g. 256 for char).
Definition: char.hpp:43
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 size
A type trait that holds the size of a (semi-)alphabet.
Definition: concept.hpp:517
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:70
constexpr auto char_is_valid_for
Returns whether a character is in the valid set of a bio::alphabet::alphabet (usually implies a bijec...
Definition: concept.hpp:395
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
decltype(bio::alphabet::to_rank(std::declval< semi_alphabet_type >())) rank_t
The rank_type of the semi-alphabet; defined as the return type of bio::alphabet::to_rank.
Definition: concept.hpp:90
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition: concept.hpp:138
constexpr auto assign_char_strictly_to
Assign a character to an alphabet object, throw if the character is not valid.
Definition: concept.hpp:461
#define BIOCPP_IS_CONSTEXPR(...)
Returns true if the expression passed to this macro can be evaluated at compile time,...
Definition: core.hpp:182
The alphabet module's namespace.
Definition: aa10li.hpp:23
provides bio::meta::priority_tag.
Customisation tag for bio::alphabet::assign_char_to.
Definition: tag.hpp:37
Customisation tag for bio::alphabet::assign_rank_to.#.
Definition: tag.hpp:29
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
An exception typically thrown by bio::alphabet::assign_char_strict.
Definition: exception.hpp:27
Provides the customisation tags for the alphabet concepts.
Provides traits to inspect some information of a type, for example its name.