SeqAn3  3.2.0
The Modern C++ library for sequence analysis.
alphabet/concept.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2022, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2022, 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 
28 namespace seqan3::custom
29 {
30 
47 template <typename t>
48 struct alphabet
49 {};
50 
52 template <typename t>
53 struct alphabet<t const> : alphabet<t>
54 {};
55 
56 template <typename t>
57 struct alphabet<t &> : alphabet<t>
58 {};
59 
60 template <typename t>
61 struct alphabet<t const &> : alphabet<t>
62 {};
64 
65 } // namespace seqan3::custom
66 
67 // ============================================================================
68 // to_rank()
69 // ============================================================================
70 
71 namespace seqan3::detail::adl_only
72 {
73 
75 template <typename... args_t>
76 void to_rank(args_t...) = delete;
77 
80 struct 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  /*return*/ seqan3::custom::alphabet<alphabet_t>::to_rank(std::forward<alphabet_t>(alphabet)) /*;*/
94  );
95 
100  template <typename alphabet_t>
101  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_t && alphabet)(
102  /*return*/ to_rank(std::forward<alphabet_t>(alphabet)) /*;*/
103  );
104 
109  template <typename alphabet_t>
110  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_t && alphabet)(
111  /*return*/ std::forward<alphabet_t>(alphabet).to_rank() /*;*/
112  );
113 };
114 
115 } // namespace seqan3::detail::adl_only
116 
117 namespace seqan3
118 {
119 
161 inline constexpr auto to_rank = detail::adl_only::to_rank_cpo{};
163 
169 template <typename semi_alphabet_type>
171  {
172  seqan3::to_rank(std::declval<semi_alphabet_type>())
173  };
174  }
175 using alphabet_rank_t = decltype(seqan3::to_rank(std::declval<semi_alphabet_type>()));
176 
177 } // namespace seqan3
178 
179 // ============================================================================
180 // assign_rank_to()
181 // ============================================================================
182 
183 namespace seqan3::detail::adl_only
184 {
185 
187 template <typename... args_t>
188 void assign_rank_to(args_t...) = delete;
189 
192 struct assign_rank_to_cpo : public detail::customisation_point_object<assign_rank_to_cpo, 2>
193 {
195  using base_t = detail::customisation_point_object<assign_rank_to_cpo, 2>;
197  using base_t::base_t;
198 
212  template <typename alphabet_t>
213  static constexpr auto
214  SEQAN3_CPO_OVERLOAD(priority_tag<2>, seqan3::alphabet_rank_t<alphabet_t> const rank, alphabet_t && alphabet)(
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
233  SEQAN3_CPO_OVERLOAD(priority_tag<1>, seqan3::alphabet_rank_t<alphabet_t> const rank, alphabet_t && alphabet)(
234  /*return*/ static_cast<alphabet_t>(assign_rank_to(rank, alphabet)) /*;*/
235  );
236 
247  template <typename alphabet_t> // least priority
248  static constexpr auto
249  SEQAN3_CPO_OVERLOAD(priority_tag<0>, seqan3::alphabet_rank_t<alphabet_t> const rank, alphabet_t && alphabet)(
250  /*return*/ static_cast<alphabet_t>(std::forward<alphabet_t>(alphabet).assign_rank(rank)) /*;*/
251  );
252 };
253 
254 } // namespace seqan3::detail::adl_only
255 
256 namespace seqan3
257 {
258 
305 inline constexpr auto assign_rank_to = detail::adl_only::assign_rank_to_cpo{};
307 } // namespace seqan3
308 
309 // ============================================================================
310 // to_char()
311 // ============================================================================
312 
313 namespace seqan3::detail::adl_only
314 {
315 
317 template <typename... args_t>
318 void to_char(args_t...) = delete;
319 
322 struct to_char_cpo : public detail::customisation_point_object<to_char_cpo, 2>
323 {
325  using base_t = detail::customisation_point_object<to_char_cpo, 2>;
327  using base_t::base_t;
328 
333  template <typename alphabet_t>
334  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_t && alphabet)(
335  /*return*/ seqan3::custom::alphabet<alphabet_t>::to_char(std::forward<alphabet_t>(alphabet)) /*;*/
336  );
337 
342  template <typename alphabet_t>
343  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_t && alphabet)(
344  /*return*/ to_char(std::forward<alphabet_t>(alphabet)) /*;*/
345  );
346 
351  template <typename alphabet_t>
352  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_t && alphabet)(
353  /*return*/ std::forward<alphabet_t>(alphabet).to_char() /*;*/
354  );
355 };
356 
357 } // namespace seqan3::detail::adl_only
358 
359 namespace seqan3
360 {
361 
404 inline constexpr auto to_char = detail::adl_only::to_char_cpo{};
406 
412 template <typename alphabet_type>
413  requires requires (alphabet_type const a) {
414  {
415  seqan3::to_char(a)
416  };
417  }
418 using alphabet_char_t = decltype(seqan3::to_char(std::declval<alphabet_type const>()));
419 
420 } // namespace seqan3
421 
422 // ============================================================================
423 // assign_char_to()
424 // ============================================================================
425 
426 namespace seqan3::detail::adl_only
427 {
428 
430 template <typename... args_t>
431 void assign_char_to(args_t...) = delete;
432 
435 struct assign_char_to_cpo : public detail::customisation_point_object<assign_char_to_cpo, 2>
436 {
438  using base_t = detail::customisation_point_object<assign_char_to_cpo, 2>;
440  using base_t::base_t;
441 
455  template <typename alphabet_t>
456  static constexpr auto
457  SEQAN3_CPO_OVERLOAD(priority_tag<2>, seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet)(
458  /*return*/ static_cast<alphabet_t>(seqan3::custom::alphabet<alphabet_t>::assign_char_to(chr, alphabet)) /*;*/
459  );
460 
474  template <typename alphabet_t>
475  static constexpr auto
476  SEQAN3_CPO_OVERLOAD(priority_tag<1>, seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet)(
477  /*return*/ static_cast<alphabet_t>(assign_char_to(chr, alphabet)) /*;*/
478  );
479 
490  template <typename alphabet_t> // least priority
491  static constexpr auto
492  SEQAN3_CPO_OVERLOAD(priority_tag<0>, seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet)(
493  /*return*/ static_cast<alphabet_t>(alphabet.assign_char(chr)) /*;*/
494  );
495 };
496 
497 } // namespace seqan3::detail::adl_only
498 
499 namespace seqan3
500 {
501 
548 inline constexpr auto assign_char_to = detail::adl_only::assign_char_to_cpo{};
550 } // namespace seqan3
551 
552 // ============================================================================
553 // char_is_valid_for()
554 // ============================================================================
555 
556 namespace seqan3::detail::adl_only
557 {
558 
560 template <typename... args_t>
561 void char_is_valid_for(args_t...) = delete;
562 
567 template <typename alphabet_t>
568 struct char_is_valid_for_cpo : public detail::customisation_point_object<char_is_valid_for_cpo<alphabet_t>, 3>
569 {
571  using base_t = detail::customisation_point_object<char_is_valid_for_cpo<alphabet_t>, 3>;
573  using base_t::base_t;
574 
578  template <typename alphabet_type>
579  using alphabet_or_type_identity =
581  std::remove_cvref_t<alphabet_type>,
582  std::type_identity<alphabet_type>>;
583 
588  template <typename alphabet_type = alphabet_t>
589  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<3>, alphabet_char_t<alphabet_type> const chr)(
590  /*return*/ seqan3::custom::alphabet<alphabet_type>::char_is_valid(chr) == true /*;*/
591  );
592 
603  template <typename alphabet_type = alphabet_t>
604  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_char_t<alphabet_type> const chr)(
605  /*return*/ char_is_valid_for(chr, alphabet_or_type_identity<alphabet_type>{}) == true /*;*/
606  );
607 
612  template <typename alphabet_type = alphabet_t>
613  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_char_t<alphabet_type> const chr)(
614  /*return*/ std::remove_cvref_t<alphabet_type>::char_is_valid(chr) == true /*;*/
615  );
616 
637  template <typename alphabet_type = alphabet_t>
638  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_char_t<alphabet_type> const chr)(
639  /*return*/ seqan3::to_char(seqan3::assign_char_to(chr, alphabet_or_type_identity<alphabet_type>{})) == chr /*;*/
640  );
641 };
642 
643 } // namespace seqan3::detail::adl_only
644 
645 namespace seqan3
646 {
647 
696 template <typename alph_t>
698  {
699  to_char(std::declval<alph_t>())
700  };
701  } // to_char() is required by some defs
702 inline constexpr auto char_is_valid_for = detail::adl_only::char_is_valid_for_cpo<alph_t>{};
704 } // namespace seqan3
705 
706 // ============================================================================
707 // assign_char_strictly_to()
708 // ============================================================================
709 
710 namespace seqan3::detail::adl_only
711 {
712 
715 struct assign_char_strictly_to_fn
716 {
718  template <typename alphabet_t>
719  constexpr decltype(auto) operator()(seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet) const
720  requires requires () {
721  {
722  seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet))
723  } -> std::convertible_to<alphabet_t>;
724  {
725  seqan3::char_is_valid_for<alphabet_t>(chr)
726  } -> std::same_as<bool>;
727  }
728  {
729  if (!seqan3::char_is_valid_for<alphabet_t>(chr))
730  throw seqan3::invalid_char_assignment{detail::type_name_as_string<alphabet_t>, chr};
731 
732  return seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet));
733  }
734 };
735 
736 } // namespace seqan3::detail::adl_only
737 
738 namespace seqan3
739 {
740 
766 inline constexpr auto assign_char_strictly_to = detail::adl_only::assign_char_strictly_to_fn{};
768 } // namespace seqan3
769 
770 // ============================================================================
771 // alphabet_size
772 // ============================================================================
773 
774 namespace seqan3::detail::adl_only
775 {
776 
778 template <typename... args_t>
779 void alphabet_size(args_t...) = delete;
780 
785 template <typename alphabet_t>
786 struct alphabet_size_cpo : public detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>
787 {
789  using base_t = detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>;
791  using base_t::base_t;
792 
796  template <typename alphabet_type>
797  using alphabet_or_type_identity =
799  && seqan3::is_constexpr_default_constructible_v<std::remove_cvref_t<alphabet_type>>,
800  std::remove_cvref_t<alphabet_type>,
801  std::type_identity<alphabet_type>>;
802 
806  template <typename alphabet_type = alphabet_t>
807  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>)(
809  );
810 
819  template <typename alphabet_type = alphabet_t>
820  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>)(
821  /*return*/ alphabet_size(alphabet_or_type_identity<alphabet_type>{}) /*;*/
822  );
823 
827  template <typename alphabet_type = alphabet_t>
828  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>)(
829  /*return*/ std::remove_cvref_t<alphabet_type>::alphabet_size /*;*/
830  );
831 };
832 
833 } // namespace seqan3::detail::adl_only
834 
835 namespace seqan3
836 {
837 
881 template <typename alph_t>
883  {
884  detail::adl_only::alphabet_size_cpo<alph_t>{}()
885  };
886  }
887 inline constexpr auto alphabet_size = detail::adl_only::alphabet_size_cpo<alph_t>{}();
888 
889 // ============================================================================
890 // semialphabet
891 // ============================================================================
892 
935 template <typename t>
936 concept semialphabet = std::totally_ordered<t> && std::copy_constructible<t> && std::is_nothrow_copy_constructible_v<t>
937  && requires (t v) {
938  {
939  seqan3::alphabet_size<t>
940  };
941  {
942  seqan3::to_rank(v)
943  };
944  };
946 
947 // ============================================================================
948 // writable_semialphabet
949 // ============================================================================
950 
986 template <typename t>
987 concept writable_semialphabet = semialphabet<t> && requires (t v, alphabet_rank_t<t> r) {
988  {
990  };
991  };
993 
994 // ============================================================================
995 // alphabet
996 // ============================================================================
997 
1026 template <typename t>
1027 concept alphabet = semialphabet<t> && requires (t v) {
1028  {
1029  seqan3::to_char(v)
1030  };
1031  };
1033 
1034 // ============================================================================
1035 // writable_alphabet
1036 // ============================================================================
1037 
1075 template <typename t>
1076 concept writable_alphabet = alphabet<t> && writable_semialphabet<t> && requires (t v, alphabet_char_t<t> c) {
1077  {
1079  };
1080  };
1082 
1083 // ============================================================================
1084 // serialisation
1085 // ============================================================================
1086 
1108 template <cereal_output_archive archive_t, semialphabet alphabet_t>
1109 alphabet_rank_t<alphabet_t> CEREAL_SAVE_MINIMAL_FUNCTION_NAME(archive_t const &, alphabet_t const & l)
1110 {
1111  return to_rank(l);
1112 }
1113 
1127 template <cereal_input_archive archive_t, typename wrapped_alphabet_t>
1128 void CEREAL_LOAD_MINIMAL_FUNCTION_NAME(archive_t const &,
1129  wrapped_alphabet_t && l,
1130  alphabet_rank_t<detail::strip_cereal_wrapper_t<wrapped_alphabet_t>> const & r)
1132 {
1133  assign_rank_to(r, static_cast<detail::strip_cereal_wrapper_t<wrapped_alphabet_t> &>(l));
1134 }
1139 } // namespace seqan3
1140 
1141 namespace seqan3::detail
1142 {
1143 // ============================================================================
1144 // constexpr_semialphabet
1145 // ============================================================================
1146 
1156 template <typename t>
1157 concept constexpr_semialphabet =
1159  // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1160  requires SEQAN3_IS_CONSTEXPR(to_rank(std::remove_reference_t<t>{}));
1161  };
1163 
1164 // ============================================================================
1165 // writable_constexpr_semialphabet
1166 // ============================================================================
1167 
1178 template <typename t>
1179 concept writable_constexpr_semialphabet =
1180  constexpr_semialphabet<t> && writable_semialphabet<t>
1181  && requires {
1182  // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1183  requires SEQAN3_IS_CONSTEXPR(seqan3::assign_rank_to(alphabet_rank_t<t>{}, std::remove_reference_t<t>{}));
1184  };
1186 
1187 // ============================================================================
1188 // constexpr_alphabet
1189 // ============================================================================
1190 
1201 template <typename t>
1202 concept constexpr_alphabet =
1203  constexpr_semialphabet<t> && alphabet<t> && requires {
1204  // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1205  requires SEQAN3_IS_CONSTEXPR(to_char(std::remove_reference_t<t>{}));
1206  };
1208 
1209 // ============================================================================
1210 // writable_constexpr_alphabet
1211 // ============================================================================
1212 
1224 template <typename t>
1225 concept writable_constexpr_alphabet =
1226  constexpr_alphabet<t> && writable_constexpr_semialphabet<t> && writable_alphabet<t>
1227  && requires {
1228  // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1229  requires SEQAN3_IS_CONSTEXPR(seqan3::assign_char_to(alphabet_char_t<t>{}, std::remove_reference_t<t>{}));
1230  };
1232 
1233 } // 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:107
constexpr auto assign_char_to
Assign a character to an alphabet object.
Definition: alphabet/concept.hpp:524
constexpr auto char_is_valid_for
Return the rank representation of a (semi-)alphabet object.
Definition: alphabet/concept.hpp:670
constexpr auto to_char
Return the char representation of an alphabet object.
Definition: alphabet/concept.hpp:386
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition: alphabet/concept.hpp:293
requires requires
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition: alphabet/concept.hpp:164
constexpr auto assign_char_strictly_to
Assign a character to an alphabet object, throw if the character is not valid.
Definition: alphabet/concept.hpp:734
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: alphabet/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:42
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: alphabet/concept.hpp:49
An exception typically thrown by seqan3::alphabet::assign_char_strict.
Definition: alphabet/exception.hpp:30
Provides traits to inspect some information of a type, for example its name.
Provides concepts that do not have equivalents in C++20.