SeqAn3  3.1.0
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 <seqan3/std/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  (
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 
120 namespace seqan3
121 {
122 
164 inline constexpr auto to_rank = detail::adl_only::to_rank_cpo{};
166 
172 template <typename semi_alphabet_type>
174  requires requires { { seqan3::to_rank(std::declval<semi_alphabet_type>()) }; }
176 using alphabet_rank_t = decltype(seqan3::to_rank(std::declval<semi_alphabet_type>()));
177 
178 } // namespace seqan3
179 
180 // ============================================================================
181 // assign_rank_to()
182 // ============================================================================
183 
184 namespace seqan3::detail::adl_only
185 {
186 
188 template <typename ...args_t>
189 void assign_rank_to(args_t ...) = delete;
190 
193 struct 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 
263 namespace seqan3
264 {
265 
312 inline constexpr auto assign_rank_to = detail::adl_only::assign_rank_to_cpo{};
314 } // namespace seqan3
315 
316 // ============================================================================
317 // to_char()
318 // ============================================================================
319 
320 namespace seqan3::detail::adl_only
321 {
322 
324 template <typename ...args_t>
325 void to_char(args_t ...) = delete;
326 
329 struct 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 
369 namespace seqan3
370 {
371 
414 inline constexpr auto to_char = detail::adl_only::to_char_cpo{};
416 
422 template <typename alphabet_type>
424  requires requires (alphabet_type const a) { { seqan3::to_char(a) }; }
426 using alphabet_char_t = decltype(seqan3::to_char(std::declval<alphabet_type const>()));
427 
428 } // namespace seqan3
429 
430 // ============================================================================
431 // assign_char_to()
432 // ============================================================================
433 
434 namespace seqan3::detail::adl_only
435 {
436 
438 template <typename ...args_t>
439 void assign_char_to(args_t ...) = delete;
440 
443 struct 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 
513 namespace seqan3
514 {
515 
562 inline constexpr auto assign_char_to = detail::adl_only::assign_char_to_cpo{};
564 } // namespace seqan3
565 
566 // ============================================================================
567 // char_is_valid_for()
568 // ============================================================================
569 
570 namespace seqan3::detail::adl_only
571 {
572 
574 template <typename ...args_t>
575 void char_is_valid_for(args_t ...) = delete;
576 
581 template <typename alphabet_t>
582 struct 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  (
605  /*return*/ seqan3::custom::alphabet<alphabet_type>::char_is_valid(chr) == true /*;*/
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 
663 namespace seqan3
664 {
665 
714 template <typename alph_t>
716  requires requires { { to_char(std::declval<alph_t>()) }; } // to_char() is required by some defs
718 inline 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 
726 namespace seqan3::detail::adl_only
727 {
728 
731 struct 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_RETURN_TYPE_CONSTRAINT(seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet)),
740  std::convertible_to, alphabet_t);
741  SEQAN3_RETURN_TYPE_CONSTRAINT(seqan3::char_is_valid_for<alphabet_t>(chr), std::same_as, bool);
742  }
744  {
745  if (!seqan3::char_is_valid_for<alphabet_t>(chr))
746  throw seqan3::invalid_char_assignment{detail::type_name_as_string<alphabet_t>, chr};
747 
748  return seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet));
749  }
750 };
751 
752 } // namespace seqan3::detail::adl_only
753 
754 namespace seqan3
755 {
756 
782 inline constexpr auto assign_char_strictly_to = detail::adl_only::assign_char_strictly_to_fn{};
784 } // namespace seqan3
785 
786 // ============================================================================
787 // alphabet_size
788 // ============================================================================
789 
790 namespace seqan3::detail::adl_only
791 {
792 
794 template <typename ...args_t>
795 void alphabet_size(args_t ...) = delete;
796 
801 template <typename alphabet_t>
802 struct alphabet_size_cpo : public detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>
803 {
805  using base_t = detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>;
807  using base_t::base_t;
808 
812  template <typename alphabet_type>
813  using alphabet_or_type_identity
815  seqan3::is_constexpr_default_constructible_v<std::remove_cvref_t<alphabet_type>>,
818 
822  template <typename alphabet_type = alphabet_t>
823  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>)
824  (
826  );
827 
836  template <typename alphabet_type = alphabet_t>
837  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>)
838  (
839  /*return*/ alphabet_size(alphabet_or_type_identity<alphabet_type>{}) /*;*/
840  );
841 
845  template <typename alphabet_type = alphabet_t>
846  static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>)
847  (
849  );
850 };
851 
852 #if SEQAN3_WORKAROUND_GCC_89953
853 template <typename alph_t>
854  requires requires { { alphabet_size_cpo<alph_t>{} }; }
855 inline constexpr auto alphabet_size_obj = alphabet_size_cpo<alph_t>{};
856 #endif // SEQAN3_WORKAROUND_GCC_89953
857 
858 } // namespace seqan3::detail::adl_only
859 
860 namespace seqan3
861 {
862 
906 #if SEQAN3_WORKAROUND_GCC_89953
907 template <typename alph_t>
909  requires requires { { detail::adl_only::alphabet_size_cpo<alph_t>{} }; } &&
910  requires { { detail::adl_only::alphabet_size_obj<alph_t>() }; } // ICE workarounds
912 inline constexpr auto alphabet_size = detail::adl_only::alphabet_size_obj<alph_t>();
913 #else // ^^^ workaround / no workaround vvv
914 template <typename alph_t>
916  requires requires { { detail::adl_only::alphabet_size_cpo<alph_t>{}() }; }
918 inline constexpr auto alphabet_size = detail::adl_only::alphabet_size_cpo<alph_t>{}();
919 #endif // SEQAN3_WORKAROUND_GCC_89953
920 
921 // ============================================================================
922 // semialphabet
923 // ============================================================================
924 
967 template <typename t>
968 SEQAN3_CONCEPT semialphabet =
969  std::totally_ordered<t> &&
970  std::copy_constructible<t> &&
971  std::is_nothrow_copy_constructible_v<t> &&
972  requires (t v)
973 {
974  { seqan3::alphabet_size<t> };
975  { seqan3::to_rank(v) };
976 };
978 
979 // ============================================================================
980 // writable_semialphabet
981 // ============================================================================
982 
1018 template <typename t>
1019 SEQAN3_CONCEPT writable_semialphabet = semialphabet<t> && requires (t v, alphabet_rank_t<t> r)
1020 {
1021  { seqan3::assign_rank_to(r, v) };
1022 };
1024 
1025 // ============================================================================
1026 // alphabet
1027 // ============================================================================
1028 
1057 template <typename t>
1058 SEQAN3_CONCEPT alphabet = semialphabet<t> && requires (t v)
1059 {
1060  { seqan3::to_char(v) };
1061 };
1063 
1064 // ============================================================================
1065 // writable_alphabet
1066 // ============================================================================
1067 
1105 template <typename t>
1106 SEQAN3_CONCEPT writable_alphabet = alphabet<t> && writable_semialphabet<t> && requires (t v, alphabet_char_t<t> c)
1107 {
1108  { seqan3::assign_char_to(c, v) };
1109 };
1111 
1112 // ============================================================================
1113 // serialisation
1114 // ============================================================================
1115 
1137 template <cereal_output_archive archive_t, semialphabet alphabet_t>
1138 alphabet_rank_t<alphabet_t> CEREAL_SAVE_MINIMAL_FUNCTION_NAME(archive_t const &, alphabet_t const & l)
1139 {
1140  return to_rank(l);
1141 }
1142 
1156 template <cereal_input_archive archive_t, typename wrapped_alphabet_t>
1157 void CEREAL_LOAD_MINIMAL_FUNCTION_NAME(archive_t const &,
1158  wrapped_alphabet_t && l,
1159  alphabet_rank_t<detail::strip_cereal_wrapper_t<wrapped_alphabet_t>> const & r)
1161 {
1162  assign_rank_to(r, static_cast<detail::strip_cereal_wrapper_t<wrapped_alphabet_t> &>(l));
1163 }
1168 } // namespace seqan3
1169 
1170 namespace seqan3::detail
1171 {
1172 // ============================================================================
1173 // constexpr_semialphabet
1174 // ============================================================================
1175 
1185 template <typename t>
1186 SEQAN3_CONCEPT constexpr_semialphabet = semialphabet<t> && requires
1187 {
1188  // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1189  requires SEQAN3_IS_CONSTEXPR(to_rank(std::remove_reference_t<t>{}));
1190 };
1192 
1193 // ============================================================================
1194 // writable_constexpr_semialphabet
1195 // ============================================================================
1196 
1207 template <typename t>
1208 SEQAN3_CONCEPT writable_constexpr_semialphabet = constexpr_semialphabet<t> && writable_semialphabet<t> && requires
1209 {
1210  // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1211  requires SEQAN3_IS_CONSTEXPR(seqan3::assign_rank_to(alphabet_rank_t<t>{}, std::remove_reference_t<t>{}));
1212 };
1214 
1215 // ============================================================================
1216 // constexpr_alphabet
1217 // ============================================================================
1218 
1229 template <typename t>
1230 SEQAN3_CONCEPT constexpr_alphabet = constexpr_semialphabet<t> && alphabet<t> && requires
1231 {
1232  // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1233  requires SEQAN3_IS_CONSTEXPR(to_char(std::remove_reference_t<t>{}));
1234 };
1236 
1237 // ============================================================================
1238 // writable_constexpr_alphabet
1239 // ============================================================================
1240 
1252 template <typename t>
1253 SEQAN3_CONCEPT writable_constexpr_alphabet =
1254  constexpr_alphabet<t> && writable_constexpr_semialphabet<t> && writable_alphabet<t> && requires
1255 {
1256  // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1257  requires SEQAN3_IS_CONSTEXPR(seqan3::assign_char_to(alphabet_char_t<t>{}, std::remove_reference_t<t>{}));
1258 };
1260 
1261 } // 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:861
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:734
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:155
typename remove_cvref< t >::type remove_cvref_t
Return the input type with const, volatile and references removed (transformation_trait shortcut).
Definition: type_traits:73
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
#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
The identity transformation (a transformation_trait that returns the input).
Definition: type_traits:87
Provides traits to inspect some information of a type, for example its name.
The <type_traits> header from C++20's standard library.