SeqAn3 3.1.0-rc.2
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
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
169template <typename semi_alphabet_type>
171 requires requires { { seqan3::to_rank(std::declval<semi_alphabet_type>()) }; }
173using alphabet_rank_t = decltype(seqan3::to_rank(std::declval<semi_alphabet_type>()));
174
175} // namespace seqan3
176
177// ============================================================================
178// assign_rank_to()
179// ============================================================================
180
181namespace seqan3::detail::adl_only
182{
183
185template <typename ...args_t>
186void assign_rank_to(args_t ...) = delete;
187
190struct assign_rank_to_cpo : public detail::customisation_point_object<assign_rank_to_cpo, 2>
191{
193 using base_t = detail::customisation_point_object<assign_rank_to_cpo, 2>;
195 using base_t::base_t;
196
210 template <typename alphabet_t>
211 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>,
213 alphabet_t && alphabet)
214 (
215 /*return*/ static_cast<alphabet_t>(seqan3::custom::alphabet<alphabet_t>::assign_rank_to(rank, alphabet)) /*;*/
216 );
217
231 template <typename alphabet_t>
232 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>,
234 alphabet_t && alphabet)
235 (
236 /*return*/ static_cast<alphabet_t>(assign_rank_to(rank, alphabet)) /*;*/
237 );
238
249 template <typename alphabet_t> // least priority
250 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>,
252 alphabet_t && alphabet)
253 (
254 /*return*/ static_cast<alphabet_t>(std::forward<alphabet_t>(alphabet).assign_rank(rank)) /*;*/
255 );
256};
257
258} // namespace seqan3::detail::adl_only
259
260namespace seqan3
261{
262
309inline constexpr auto assign_rank_to = detail::adl_only::assign_rank_to_cpo{};
311} // namespace seqan3
312
313// ============================================================================
314// to_char()
315// ============================================================================
316
317namespace seqan3::detail::adl_only
318{
319
321template <typename ...args_t>
322void to_char(args_t ...) = delete;
323
326struct to_char_cpo : public detail::customisation_point_object<to_char_cpo, 2>
327{
329 using base_t = detail::customisation_point_object<to_char_cpo, 2>;
331 using base_t::base_t;
332
337 template <typename alphabet_t>
338 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_t && alphabet)
339 (
340 /*return*/ seqan3::custom::alphabet<alphabet_t>::to_char(std::forward<alphabet_t>(alphabet)) /*;*/
341 );
342
347 template <typename alphabet_t>
348 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_t && alphabet)
349 (
350 /*return*/ to_char(std::forward<alphabet_t>(alphabet)) /*;*/
351 );
352
357 template <typename alphabet_t>
358 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_t && alphabet)
359 (
360 /*return*/ std::forward<alphabet_t>(alphabet).to_char() /*;*/
361 );
362};
363
364} // namespace seqan3::detail::adl_only
365
366namespace seqan3
367{
368
411inline constexpr auto to_char = detail::adl_only::to_char_cpo{};
413
419template <typename alphabet_type>
421 requires requires (alphabet_type const a) { { seqan3::to_char(a) }; }
423using alphabet_char_t = decltype(seqan3::to_char(std::declval<alphabet_type const>()));
424
425} // namespace seqan3
426
427// ============================================================================
428// assign_char_to()
429// ============================================================================
430
431namespace seqan3::detail::adl_only
432{
433
435template <typename ...args_t>
436void assign_char_to(args_t ...) = delete;
437
440struct assign_char_to_cpo : public detail::customisation_point_object<assign_char_to_cpo, 2>
441{
443 using base_t = detail::customisation_point_object<assign_char_to_cpo, 2>;
445 using base_t::base_t;
446
460 template <typename alphabet_t>
461 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>,
463 alphabet_t && alphabet)
464 (
465 /*return*/ static_cast<alphabet_t>(seqan3::custom::alphabet<alphabet_t>::assign_char_to(chr, alphabet)) /*;*/
466 );
467
481 template <typename alphabet_t>
482 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>,
484 alphabet_t && alphabet)
485 (
486 /*return*/ static_cast<alphabet_t>(assign_char_to(chr, alphabet)) /*;*/
487 );
488
499 template <typename alphabet_t> // least priority
500 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>,
502 alphabet_t && alphabet)
503 (
504 /*return*/ static_cast<alphabet_t>(alphabet.assign_char(chr)) /*;*/
505 );
506};
507
508} // namespace seqan3::detail::adl_only
509
510namespace seqan3
511{
512
559inline constexpr auto assign_char_to = detail::adl_only::assign_char_to_cpo{};
561} // namespace seqan3
562
563// ============================================================================
564// char_is_valid_for()
565// ============================================================================
566
567namespace seqan3::detail::adl_only
568{
569
571template <typename ...args_t>
572void char_is_valid_for(args_t ...) = delete;
573
578template <typename alphabet_t>
579struct char_is_valid_for_cpo : public detail::customisation_point_object<char_is_valid_for_cpo<alphabet_t>, 3>
580{
582 using base_t = detail::customisation_point_object<char_is_valid_for_cpo<alphabet_t>, 3>;
584 using base_t::base_t;
585
589 template <typename alphabet_type>
590 using alphabet_or_type_identity
594
599 template <typename alphabet_type = alphabet_t>
600 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<3>, alphabet_char_t<alphabet_type> const chr)
601 (
603 );
604
615 template <typename alphabet_type = alphabet_t>
616 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_char_t<alphabet_type> const chr)
617 (
618 /*return*/ char_is_valid_for(chr, alphabet_or_type_identity<alphabet_type>{}) == true /*;*/
619 );
620
625 template <typename alphabet_type = alphabet_t>
626 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_char_t<alphabet_type> const chr)
627 (
628 /*return*/ std::remove_cvref_t<alphabet_type>::char_is_valid(chr) == true /*;*/
629 );
630
651 template <typename alphabet_type = alphabet_t>
652 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_char_t<alphabet_type> const chr)
653 (
654 /*return*/ seqan3::to_char(seqan3::assign_char_to(chr, alphabet_or_type_identity<alphabet_type>{})) == chr /*;*/
655 );
656};
657
658} // namespace seqan3::detail::adl_only
659
660namespace seqan3
661{
662
711template <typename alph_t>
713 requires requires { { to_char(std::declval<alph_t>()) }; } // to_char() is required by some defs
715inline constexpr auto char_is_valid_for = detail::adl_only::char_is_valid_for_cpo<alph_t>{};
717} // namespace seqan3
718
719// ============================================================================
720// assign_char_strictly_to()
721// ============================================================================
722
723namespace seqan3::detail::adl_only
724{
725
728struct assign_char_strictly_to_fn
729{
731 template <typename alphabet_t>
732 constexpr decltype(auto) operator()(seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet) const
734 requires requires ()
735 {
736 SEQAN3_RETURN_TYPE_CONSTRAINT(seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet)),
737 std::convertible_to, alphabet_t);
738 SEQAN3_RETURN_TYPE_CONSTRAINT(seqan3::char_is_valid_for<alphabet_t>(chr), std::same_as, bool);
739 }
741 {
742 if (!seqan3::char_is_valid_for<alphabet_t>(chr))
743 throw seqan3::invalid_char_assignment{detail::type_name_as_string<alphabet_t>, chr};
744
745 return seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet));
746 }
747};
748
749} // namespace seqan3::detail::adl_only
750
751namespace seqan3
752{
753
779inline constexpr auto assign_char_strictly_to = detail::adl_only::assign_char_strictly_to_fn{};
781} // namespace seqan3
782
783// ============================================================================
784// alphabet_size
785// ============================================================================
786
787namespace seqan3::detail::adl_only
788{
789
791template <typename ...args_t>
792void alphabet_size(args_t ...) = delete;
793
798template <typename alphabet_t>
799struct alphabet_size_cpo : public detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>
800{
802 using base_t = detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>;
804 using base_t::base_t;
805
809 template <typename alphabet_type>
810 using alphabet_or_type_identity
812 seqan3::is_constexpr_default_constructible_v<std::remove_cvref_t<alphabet_type>>,
815
819 template <typename alphabet_type = alphabet_t>
820 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>)
821 (
823 );
824
833 template <typename alphabet_type = alphabet_t>
834 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>)
835 (
836 /*return*/ alphabet_size(alphabet_or_type_identity<alphabet_type>{}) /*;*/
837 );
838
842 template <typename alphabet_type = alphabet_t>
843 static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>)
844 (
846 );
847};
848
849#if SEQAN3_WORKAROUND_GCC_89953
850template <typename alph_t>
851 requires requires { { alphabet_size_cpo<alph_t>{} }; }
852inline constexpr auto alphabet_size_obj = alphabet_size_cpo<alph_t>{};
853#endif // SEQAN3_WORKAROUND_GCC_89953
854
855} // namespace seqan3::detail::adl_only
856
857namespace seqan3
859
903#if SEQAN3_WORKAROUND_GCC_89953
904template <typename alph_t>
906 requires requires { { detail::adl_only::alphabet_size_cpo<alph_t>{} }; } &&
907 requires { { detail::adl_only::alphabet_size_obj<alph_t>() }; } // ICE workarounds
909inline constexpr auto alphabet_size = detail::adl_only::alphabet_size_obj<alph_t>();
910#else // ^^^ workaround / no workaround vvv
911template <typename alph_t>
913 requires requires { { detail::adl_only::alphabet_size_cpo<alph_t>{}() }; }
915inline constexpr auto alphabet_size = detail::adl_only::alphabet_size_cpo<alph_t>{}();
916#endif // SEQAN3_WORKAROUND_GCC_89953
917
918// ============================================================================
919// semialphabet
920// ============================================================================
921
964template <typename t>
965SEQAN3_CONCEPT semialphabet =
966 std::totally_ordered<t> &&
967 std::copy_constructible<t> &&
968 std::is_nothrow_copy_constructible_v<t> &&
969 requires (t v)
970{
971 { seqan3::alphabet_size<t> };
972 { seqan3::to_rank(v) };
973};
975
976// ============================================================================
977// writable_semialphabet
978// ============================================================================
979
1015template <typename t>
1016SEQAN3_CONCEPT writable_semialphabet = semialphabet<t> && requires (t v, alphabet_rank_t<t> r)
1017{
1018 { seqan3::assign_rank_to(r, v) };
1019};
1021
1022// ============================================================================
1023// alphabet
1024// ============================================================================
1025
1054template <typename t>
1055SEQAN3_CONCEPT alphabet = semialphabet<t> && requires (t v)
1056{
1057 { seqan3::to_char(v) };
1058};
1060
1061// ============================================================================
1062// writable_alphabet
1063// ============================================================================
1064
1102template <typename t>
1103SEQAN3_CONCEPT writable_alphabet = alphabet<t> && writable_semialphabet<t> && requires (t v, alphabet_char_t<t> c)
1104{
1105 { seqan3::assign_char_to(c, v) };
1106};
1108
1109// ============================================================================
1110// serialisation
1111// ============================================================================
1112
1134template <cereal_output_archive archive_t, semialphabet alphabet_t>
1135alphabet_rank_t<alphabet_t> CEREAL_SAVE_MINIMAL_FUNCTION_NAME(archive_t const &, alphabet_t const & l)
1136{
1137 return to_rank(l);
1138}
1139
1153template <cereal_input_archive archive_t, typename wrapped_alphabet_t>
1154void CEREAL_LOAD_MINIMAL_FUNCTION_NAME(archive_t const &,
1155 wrapped_alphabet_t && l,
1156 alphabet_rank_t<detail::strip_cereal_wrapper_t<wrapped_alphabet_t>> const & r)
1158{
1159 assign_rank_to(r, static_cast<detail::strip_cereal_wrapper_t<wrapped_alphabet_t> &>(l));
1160}
1165} // namespace seqan3
1166
1167namespace seqan3::detail
1168{
1169// ============================================================================
1170// constexpr_semialphabet
1171// ============================================================================
1172
1182template <typename t>
1183SEQAN3_CONCEPT constexpr_semialphabet = semialphabet<t> && requires
1184{
1185 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1187};
1189
1190// ============================================================================
1191// writable_constexpr_semialphabet
1192// ============================================================================
1193
1204template <typename t>
1205SEQAN3_CONCEPT writable_constexpr_semialphabet = constexpr_semialphabet<t> && writable_semialphabet<t> && requires
1206{
1207 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1209};
1211
1212// ============================================================================
1213// constexpr_alphabet
1214// ============================================================================
1215
1226template <typename t>
1227SEQAN3_CONCEPT constexpr_alphabet = constexpr_semialphabet<t> && alphabet<t> && requires
1228{
1229 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1231};
1233
1234// ============================================================================
1235// writable_constexpr_alphabet
1236// ============================================================================
1237
1249template <typename t>
1250SEQAN3_CONCEPT writable_constexpr_alphabet =
1251 constexpr_alphabet<t> && writable_constexpr_semialphabet<t> && writable_alphabet<t> && requires
1252{
1253 // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1255};
1257
1258} // 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.
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
Provides concepts for core language types and relations that don't have concepts in C++20 (yet).
constexpr auto assign_char_to
Assign a character to an alphabet object.
Definition: concept.hpp:523
constexpr auto to_char
Return the char representation of an alphabet object.
Definition: concept.hpp:384
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:164
constexpr auto alphabet_size
A type trait that holds the size of a (semi-)alphabet.
Definition: concept.hpp:858
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition: concept.hpp:291
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:396
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:667
constexpr auto assign_char_strictly_to
Assign a character to an alphabet object, throw if the character is not valid.
Definition: concept.hpp:731
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:155
#define SEQAN3_IS_CONSTEXPR(...)
Returns true if the expression passed to this macro can be evaluated at compile time,...
Definition: basic.hpp:28
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: cigar_operation_table.hpp:2
#define SEQAN3_RETURN_TYPE_CONSTRAINT(expression, concept_name,...)
Same as writing {expression} -> concept_name<type1[, ...]> in a concept definition.
Definition: platform.hpp:57
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.
Provides C++20 additions to the type_traits header.