SeqAn3 3.2.0-rc.1
The Modern C++ library for sequence analysis.
concept.hpp
Go to the documentation of this file.
1// -----------------------------------------------------------------------------------------------------
2// Copyright (c) 2006-2021, Knut Reinert & Freie Universität Berlin
3// Copyright (c) 2016-2021, 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
15#include <type_traits>
16
23
24// ============================================================================
25// forwards
26// ============================================================================
27
28namespace seqan3::custom
29{
30
47template <typename t>
49{};
50
52template <typename t>
53struct alphabet<t const> : alphabet<t>
54{};
55
56template <typename t>
57struct alphabet<t &> : alphabet<t>
58{};
59
60template <typename t>
61struct alphabet<t const &> : alphabet<t>
62{};
64
65} // namespace seqan3::custom
66
67// ============================================================================
68// to_rank()
69// ============================================================================
70
71namespace seqan3::detail::adl_only
72{
73
75template <typename ...args_t>
76void to_rank(args_t ...) = delete;
77
80struct to_rank_cpo : public detail::customisation_point_object<to_rank_cpo, 2>
81{
83 using base_t = detail::customisation_point_object<to_rank_cpo, 2>;
85 using base_t::base_t;
86
91 template <typename alphabet_t>
92 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_t && alphabet)
93 (
94 /*return*/ seqan3::custom::alphabet<alphabet_t>::to_rank(std::forward<alphabet_t>(alphabet)) /*;*/
95 );
96
101 template <typename alphabet_t>
102 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_t && alphabet)
103 (
104 /*return*/ to_rank(std::forward<alphabet_t>(alphabet)) /*;*/
105 );
106
111 template <typename alphabet_t>
112 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_t && alphabet)
113 (
114 /*return*/ std::forward<alphabet_t>(alphabet).to_rank() /*;*/
115 );
116};
117
118} // namespace seqan3::detail::adl_only
119
120namespace seqan3
121{
122
164inline constexpr auto to_rank = detail::adl_only::to_rank_cpo{};
166
172template <typename semi_alphabet_type>
174 requires requires { { seqan3::to_rank(std::declval<semi_alphabet_type>()) }; }
176using alphabet_rank_t = decltype(seqan3::to_rank(std::declval<semi_alphabet_type>()));
177
178} // namespace seqan3
179
180// ============================================================================
181// assign_rank_to()
182// ============================================================================
183
184namespace seqan3::detail::adl_only
185{
186
188template <typename ...args_t>
189void assign_rank_to(args_t ...) = delete;
190
193struct assign_rank_to_cpo : public detail::customisation_point_object<assign_rank_to_cpo, 2>
194{
196 using base_t = detail::customisation_point_object<assign_rank_to_cpo, 2>;
198 using base_t::base_t;
199
213 template <typename alphabet_t>
214 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>,
216 alphabet_t && alphabet)
217 (
218 /*return*/ static_cast<alphabet_t>(seqan3::custom::alphabet<alphabet_t>::assign_rank_to(rank, alphabet)) /*;*/
219 );
220
234 template <typename alphabet_t>
235 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>,
237 alphabet_t && alphabet)
238 (
239 /*return*/ static_cast<alphabet_t>(assign_rank_to(rank, alphabet)) /*;*/
240 );
241
252 template <typename alphabet_t> // least priority
253 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>,
255 alphabet_t && alphabet)
256 (
257 /*return*/ static_cast<alphabet_t>(std::forward<alphabet_t>(alphabet).assign_rank(rank)) /*;*/
258 );
259};
260
261} // namespace seqan3::detail::adl_only
262
263namespace seqan3
264{
265
312inline constexpr auto assign_rank_to = detail::adl_only::assign_rank_to_cpo{};
314} // namespace seqan3
315
316// ============================================================================
317// to_char()
318// ============================================================================
319
320namespace seqan3::detail::adl_only
321{
322
324template <typename ...args_t>
325void to_char(args_t ...) = delete;
326
329struct to_char_cpo : public detail::customisation_point_object<to_char_cpo, 2>
330{
332 using base_t = detail::customisation_point_object<to_char_cpo, 2>;
334 using base_t::base_t;
335
340 template <typename alphabet_t>
341 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_t && alphabet)
342 (
343 /*return*/ seqan3::custom::alphabet<alphabet_t>::to_char(std::forward<alphabet_t>(alphabet)) /*;*/
344 );
345
350 template <typename alphabet_t>
351 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_t && alphabet)
352 (
353 /*return*/ to_char(std::forward<alphabet_t>(alphabet)) /*;*/
354 );
355
360 template <typename alphabet_t>
361 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_t && alphabet)
362 (
363 /*return*/ std::forward<alphabet_t>(alphabet).to_char() /*;*/
364 );
365};
366
367} // namespace seqan3::detail::adl_only
368
369namespace seqan3
370{
371
414inline constexpr auto to_char = detail::adl_only::to_char_cpo{};
416
422template <typename alphabet_type>
424 requires requires (alphabet_type const a) { { seqan3::to_char(a) }; }
426using alphabet_char_t = decltype(seqan3::to_char(std::declval<alphabet_type const>()));
427
428} // namespace seqan3
429
430// ============================================================================
431// assign_char_to()
432// ============================================================================
433
434namespace seqan3::detail::adl_only
435{
436
438template <typename ...args_t>
439void assign_char_to(args_t ...) = delete;
440
443struct assign_char_to_cpo : public detail::customisation_point_object<assign_char_to_cpo, 2>
444{
446 using base_t = detail::customisation_point_object<assign_char_to_cpo, 2>;
448 using base_t::base_t;
449
463 template <typename alphabet_t>
464 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>,
466 alphabet_t && alphabet)
467 (
468 /*return*/ static_cast<alphabet_t>(seqan3::custom::alphabet<alphabet_t>::assign_char_to(chr, alphabet)) /*;*/
469 );
470
484 template <typename alphabet_t>
485 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>,
487 alphabet_t && alphabet)
488 (
489 /*return*/ static_cast<alphabet_t>(assign_char_to(chr, alphabet)) /*;*/
490 );
491
502 template <typename alphabet_t> // least priority
503 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>,
505 alphabet_t && alphabet)
506 (
507 /*return*/ static_cast<alphabet_t>(alphabet.assign_char(chr)) /*;*/
508 );
509};
510
511} // namespace seqan3::detail::adl_only
512
513namespace seqan3
514{
515
562inline constexpr auto assign_char_to = detail::adl_only::assign_char_to_cpo{};
564} // namespace seqan3
565
566// ============================================================================
567// char_is_valid_for()
568// ============================================================================
569
570namespace seqan3::detail::adl_only
571{
572
574template <typename ...args_t>
575void char_is_valid_for(args_t ...) = delete;
576
581template <typename alphabet_t>
582struct char_is_valid_for_cpo : public detail::customisation_point_object<char_is_valid_for_cpo<alphabet_t>, 3>
583{
585 using base_t = detail::customisation_point_object<char_is_valid_for_cpo<alphabet_t>, 3>;
587 using base_t::base_t;
588
592 template <typename alphabet_type>
593 using alphabet_or_type_identity
597
602 template <typename alphabet_type = alphabet_t>
603 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<3>, alphabet_char_t<alphabet_type> const chr)
604 (
606 );
607
618 template <typename alphabet_type = alphabet_t>
619 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_char_t<alphabet_type> const chr)
620 (
621 /*return*/ char_is_valid_for(chr, alphabet_or_type_identity<alphabet_type>{}) == true /*;*/
622 );
623
628 template <typename alphabet_type = alphabet_t>
629 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_char_t<alphabet_type> const chr)
630 (
631 /*return*/ std::remove_cvref_t<alphabet_type>::char_is_valid(chr) == true /*;*/
632 );
633
654 template <typename alphabet_type = alphabet_t>
655 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_char_t<alphabet_type> const chr)
656 (
657 /*return*/ seqan3::to_char(seqan3::assign_char_to(chr, alphabet_or_type_identity<alphabet_type>{})) == chr /*;*/
658 );
659};
660
661} // namespace seqan3::detail::adl_only
662
663namespace seqan3
664{
665
714template <typename alph_t>
716 requires requires { { to_char(std::declval<alph_t>()) }; } // to_char() is required by some defs
718inline constexpr auto char_is_valid_for = detail::adl_only::char_is_valid_for_cpo<alph_t>{};
720} // namespace seqan3
721
722// ============================================================================
723// assign_char_strictly_to()
724// ============================================================================
725
726namespace seqan3::detail::adl_only
727{
728
731struct assign_char_strictly_to_fn
732{
734 template <typename alphabet_t>
735 constexpr decltype(auto) operator()(seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet) const
737 requires requires ()
738 {
739 {seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet))} -> std::convertible_to<alphabet_t>;
740 {seqan3::char_is_valid_for<alphabet_t>(chr)} -> std::same_as<bool>;
741 }
743 {
744 if (!seqan3::char_is_valid_for<alphabet_t>(chr))
745 throw seqan3::invalid_char_assignment{detail::type_name_as_string<alphabet_t>, chr};
746
747 return seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet));
748 }
749};
750
751} // namespace seqan3::detail::adl_only
752
753namespace seqan3
754{
755
781inline constexpr auto assign_char_strictly_to = detail::adl_only::assign_char_strictly_to_fn{};
783} // namespace seqan3
784
785// ============================================================================
786// alphabet_size
787// ============================================================================
788
789namespace seqan3::detail::adl_only
790{
791
793template <typename ...args_t>
794void alphabet_size(args_t ...) = delete;
795
800template <typename alphabet_t>
801struct alphabet_size_cpo : public detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>
802{
804 using base_t = detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>;
806 using base_t::base_t;
807
811 template <typename alphabet_type>
812 using alphabet_or_type_identity
814 seqan3::is_constexpr_default_constructible_v<std::remove_cvref_t<alphabet_type>>,
817
821 template <typename alphabet_type = alphabet_t>
822 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>)
823 (
825 );
826
835 template <typename alphabet_type = alphabet_t>
836 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>)
837 (
838 /*return*/ alphabet_size(alphabet_or_type_identity<alphabet_type>{}) /*;*/
839 );
840
844 template <typename alphabet_type = alphabet_t>
845 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>)
848 );
849};
850
851} // namespace seqan3::detail::adl_only
853namespace seqan3
854{
855
899template <typename alph_t>
901 requires requires { { detail::adl_only::alphabet_size_cpo<alph_t>{}() }; }
903inline constexpr auto alphabet_size = detail::adl_only::alphabet_size_cpo<alph_t>{}();
904
905// ============================================================================
906// semialphabet
907// ============================================================================
908
951template <typename t>
952concept semialphabet =
953 std::totally_ordered<t> &&
954 std::copy_constructible<t> &&
955 std::is_nothrow_copy_constructible_v<t> &&
956 requires (t v)
957{
958 { seqan3::alphabet_size<t> };
959 { seqan3::to_rank(v) };
960};
962
963// ============================================================================
964// writable_semialphabet
965// ============================================================================
966
1002template <typename t>
1003concept writable_semialphabet = semialphabet<t> && requires (t v, alphabet_rank_t<t> r)
1004{
1005 { seqan3::assign_rank_to(r, v) };
1006};
1008
1009// ============================================================================
1010// alphabet
1011// ============================================================================
1012
1041template <typename t>
1042concept alphabet = semialphabet<t> && requires (t v)
1043{
1044 { seqan3::to_char(v) };
1045};
1047
1048// ============================================================================
1049// writable_alphabet
1050// ============================================================================
1051
1089template <typename t>
1090concept writable_alphabet = alphabet<t> && writable_semialphabet<t> && requires (t v, alphabet_char_t<t> c)
1091{
1092 { seqan3::assign_char_to(c, v) };
1093};
1095
1096// ============================================================================
1097// serialisation
1098// ============================================================================
1099
1121template <cereal_output_archive archive_t, semialphabet alphabet_t>
1122alphabet_rank_t<alphabet_t> CEREAL_SAVE_MINIMAL_FUNCTION_NAME(archive_t const &, alphabet_t const & l)
1123{
1124 return to_rank(l);
1125}
1126
1140template <cereal_input_archive archive_t, typename wrapped_alphabet_t>
1141void CEREAL_LOAD_MINIMAL_FUNCTION_NAME(archive_t const &,
1142 wrapped_alphabet_t && l,
1143 alphabet_rank_t<detail::strip_cereal_wrapper_t<wrapped_alphabet_t>> const & r)
1145{
1146 assign_rank_to(r, static_cast<detail::strip_cereal_wrapper_t<wrapped_alphabet_t> &>(l));
1147}
1152} // namespace seqan3
1153
1154namespace seqan3::detail
1155{
1156// ============================================================================
1157// constexpr_semialphabet
1158// ============================================================================
1159
1169template <typename t>
1170concept constexpr_semialphabet = semialphabet<t> && requires
1171{
1172 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1173 requires SEQAN3_IS_CONSTEXPR(to_rank(std::remove_reference_t<t>{}));
1174};
1176
1177// ============================================================================
1178// writable_constexpr_semialphabet
1179// ============================================================================
1180
1191template <typename t>
1192concept writable_constexpr_semialphabet = constexpr_semialphabet<t> && writable_semialphabet<t> && requires
1193{
1194 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1195 requires SEQAN3_IS_CONSTEXPR(seqan3::assign_rank_to(alphabet_rank_t<t>{}, std::remove_reference_t<t>{}));
1196};
1198
1199// ============================================================================
1200// constexpr_alphabet
1201// ============================================================================
1202
1213template <typename t>
1214concept constexpr_alphabet = constexpr_semialphabet<t> && alphabet<t> && requires
1215{
1216 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1217 requires SEQAN3_IS_CONSTEXPR(to_char(std::remove_reference_t<t>{}));
1218};
1220
1221// ============================================================================
1222// writable_constexpr_alphabet
1223// ============================================================================
1224
1236template <typename t>
1237concept writable_constexpr_alphabet =
1238 constexpr_alphabet<t> && writable_constexpr_semialphabet<t> && writable_alphabet<t> && requires
1239{
1240 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1241 requires SEQAN3_IS_CONSTEXPR(seqan3::assign_char_to(alphabet_char_t<t>{}, std::remove_reference_t<t>{}));
1242};
1244
1245} // namespace seqan3::detail
Exceptions thrown by entities in the alphabet module.
Provides various type traits on generic types.
Adaptions of concepts from the Cereal library.
Provides concepts for core language types and relations that don't have concepts in C++20 (yet).
Helper utilities for defining customisation point objects (CPOs).
#define SEQAN3_CPO_OVERLOAD(...)
A macro that helps to define a seqan3::detail::customisation_point_object.
Definition: customisation_point.hpp:102
constexpr auto assign_char_to
Assign a character to an alphabet object.
Definition: concept.hpp:526
constexpr auto to_char
Return the char representation of an alphabet object.
Definition: concept.hpp:387
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:167
constexpr auto alphabet_size
A type trait that holds the size of a (semi-)alphabet.
Definition: concept.hpp:846
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition: concept.hpp:294
decltype(seqan3::to_char(std::declval< alphabet_type const >())) alphabet_char_t
The char_type of the alphabet; defined as the return type of seqan3::to_char.
Definition: concept.hpp:399
constexpr auto char_is_valid_for
Returns whether a character is in the valid set of a seqan3::alphabet (usually implies a bijective ma...
Definition: concept.hpp:670
constexpr auto assign_char_strictly_to
Assign a character to an alphabet object, throw if the character is not valid.
Definition: concept.hpp:733
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:155
The generic alphabet concept that covers most data types used in ranges.
The basis for seqan3::alphabet, but requires only rank interface (not char).
Refines seqan3::alphabet and adds assignability.
A refinement of seqan3::semialphabet that adds assignability.
A namespace for third party and standard library specialisations of SeqAn customisation points.
Definition: char.hpp:44
The main SeqAn3 namespace.
Definition: aligned_sequence_concept.hpp:29
A type that can be specialised to provide customisation point implementations so that third party typ...
Definition: concept.hpp:49
An exception typically thrown by seqan3::alphabet::assign_char_strict.
Definition: exception.hpp:30
Provides traits to inspect some information of a type, for example its name.