SeqAn3  3.0.0
The Modern C++ library for sequence analysis.
concept.hpp
Go to the documentation of this file.
1 // -----------------------------------------------------------------------------------------------------
2 // Copyright (c) 2006-2019, Knut Reinert & Freie Universität Berlin
3 // Copyright (c) 2016-2019, 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 <iostream>
16 
26 #include <seqan3/std/concepts>
27 
28 // ============================================================================
29 // to_rank()
30 // ============================================================================
31 
33 {
34 
36 struct to_rank_fn
37 {
38 private:
39  SEQAN3_CPO_IMPL(2, to_rank(v) ) // ADL
40  SEQAN3_CPO_IMPL(1, seqan3::custom::to_rank(v) ) // customisation namespace
41  SEQAN3_CPO_IMPL(0, v.to_rank() ) // member
42 
43 public:
45  template <typename alph_t>
47  requires requires (alph_t const a) { { impl(priority_tag<2>{}, a) }; }
49  constexpr auto operator()(alph_t const a) const noexcept
50  {
51  static_assert(noexcept(impl(priority_tag<2>{}, a)),
52  "Only overloads that are marked noexcept are picked up by seqan3::to_rank().");
53  static_assert(std::Constructible<size_t, decltype(impl(priority_tag<2>{}, a))>,
54  "The return type of your to_rank() implementation must be convertible to size_t.");
55 
56  return impl(priority_tag<2>{}, a);
57  }
58 };
59 
60 } // namespace seqan3::detail::adl::only
61 
62 namespace seqan3
63 {
64 
103 inline constexpr auto to_rank = detail::adl::only::to_rank_fn{};
105 
108 template <typename semi_alphabet_type>
110  requires requires { { seqan3::to_rank(std::declval<semi_alphabet_type>()) }; }
112 using alphabet_rank_t = decltype(seqan3::to_rank(std::declval<semi_alphabet_type>()));
113 
114 } // namespace seqan3
115 
116 // ============================================================================
117 // assign_rank_to()
118 // ============================================================================
119 
121 {
122 
125 struct assign_rank_to_fn
126 {
127 private:
128  SEQAN3_CPO_IMPL(2, (assign_rank_to(args..., v) )) // ADL
129  SEQAN3_CPO_IMPL(1, (seqan3::custom::assign_rank_to(args..., v) )) // customisation namespace
130  SEQAN3_CPO_IMPL(0, (v.assign_rank(args...) )) // member
131 
132 public:
134  template <typename alph_t>
136  requires requires (seqan3::alphabet_rank_t<alph_t> const r, alph_t & a)
137  { { impl(priority_tag<2>{}, a, r) }; }
139  constexpr alph_t & operator()(seqan3::alphabet_rank_t<alph_t> const r, alph_t & a) const noexcept
140  {
141  static_assert(noexcept(impl(priority_tag<2>{}, a, r)),
142  "Only overloads that are marked noexcept are picked up by seqan3::assign_rank_to().");
143  static_assert(std::Same<alph_t &, decltype(impl(priority_tag<2>{}, a, r))>,
144  "The return type of your assign_rank_to() implementation must be 'alph_t &'.");
145 
146  return impl(priority_tag<2>{}, a, r);
147  }
148 
150  template <typename alph_t>
152  requires requires (seqan3::alphabet_rank_t<alph_t> const r, alph_t & a)
153  { { impl(priority_tag<2>{}, a, r) }; } && (!std::is_lvalue_reference_v<alph_t>)
155  constexpr alph_t operator()(seqan3::alphabet_rank_t<alph_t> const r, alph_t && a) const noexcept
156  {
157  return (*this)(r, a); // call above function but return by value
158  }
159 };
160 
161 } // namespace seqan3::detail::adl::only
162 
163 namespace seqan3
164 {
165 
207 inline constexpr auto assign_rank_to = detail::adl::only::assign_rank_to_fn{};
209 } // namespace seqan3
210 
211 // ============================================================================
212 // to_char()
213 // ============================================================================
214 
216 {
217 
219 struct to_char_fn
220 {
221 private:
222  SEQAN3_CPO_IMPL(2, to_char(v) ) // ADL
223  SEQAN3_CPO_IMPL(1, seqan3::custom::to_char(v) ) // customisation namespace
224  SEQAN3_CPO_IMPL(0, v.to_char() ) // member
225 
226 public:
228  template <typename alph_t>
230  requires requires (alph_t const a) { { impl(priority_tag<2>{}, a) }; }
232  constexpr decltype(auto) operator()(alph_t const a) const noexcept
233  {
234  static_assert(noexcept(impl(priority_tag<2>{}, a)),
235  "Only overloads that are marked noexcept are picked up by seqan3::to_char().");
236 
237  return impl(priority_tag<2>{}, a);
238  }
239 };
240 
241 } // namespace seqan3::detail::adl::only
242 
243 namespace seqan3
244 {
245 
285 inline constexpr auto to_char = detail::adl::only::to_char_fn{};
287 
290 template <typename alphabet_type>
292  requires requires (alphabet_type const a) { { seqan3::to_char(a) }; }
294 using alphabet_char_t = decltype(seqan3::to_char(std::declval<alphabet_type const>()));
295 
296 } // namespace seqan3
297 
298 // ============================================================================
299 // assign_char_to()
300 // ============================================================================
301 
302 namespace seqan3::custom
303 {
305 void char_is_valid_for(); // forward
307 } // seqan3::custom
308 
310 {
313 struct assign_char_to_fn
314 {
315 private:
316  SEQAN3_CPO_IMPL(2, (assign_char_to(args..., v) )) // ADL
317  SEQAN3_CPO_IMPL(1, (seqan3::custom::assign_char_to(args..., v) )) // customisation namespace
318  SEQAN3_CPO_IMPL(0, (v.assign_char(args...) )) // member
319 
320 public:
322  template <typename alph_t>
324  requires requires (seqan3::alphabet_char_t<alph_t> const r, alph_t & a)
325  { { impl(priority_tag<2>{}, a, r) }; }
327  constexpr alph_t & operator()(seqan3::alphabet_char_t<alph_t> const r, alph_t & a) const noexcept
328  {
329  static_assert(noexcept(impl(priority_tag<2>{}, a, r)),
330  "Only overloads that are marked noexcept are picked up by seqan3::assign_char_to().");
331  static_assert(std::Same<alph_t &, decltype(impl(priority_tag<2>{}, a, r))>,
332  "The return type of your assign_char_to() implementation must be 'alph_t &'.");
333 
334  return impl(priority_tag<2>{}, a, r);
335  }
336 
338  template <typename alph_t>
340  requires requires (seqan3::alphabet_char_t<alph_t> const r, alph_t & a)
341  { { impl(priority_tag<2>{}, a, r) }; } && (!std::is_lvalue_reference_v<alph_t>)
343  constexpr alph_t operator()(seqan3::alphabet_char_t<alph_t> const r, alph_t && a) const noexcept
344  {
345  return (*this)(r, a); // call above function but return by value
346  }
347 };
348 
349 } // namespace seqan3::detail::adl::only
350 
351 namespace seqan3
352 {
353 
395 inline constexpr auto assign_char_to = detail::adl::only::assign_char_to_fn{};
397 } // namespace seqan3
398 
399 // ============================================================================
400 // char_is_valid_for()
401 // ============================================================================
402 
403 namespace seqan3::custom
404 {
406 void char_is_valid_for(); // forward
408 } // seqan3::custom
409 
411 {
417 template <typename alph_t,
419  remove_cvref_t<alph_t>,
421 struct char_is_valid_for_fn
422 {
423 private:
424  SEQAN3_CPO_IMPL(3, (char_is_valid_for(v, s_alph_t{}) )) // ADL
425  SEQAN3_CPO_IMPL(2, (seqan3::custom::char_is_valid_for(v, s_alph_t{}) )) // customisation ns
426  SEQAN3_CPO_IMPL(1, (deferred_type_t<remove_cvref_t<alph_t>, decltype(v)>::char_is_valid(v) )) // member
427  SEQAN3_CPO_IMPL(0, (to_char(assign_char_to(v, s_alph_t{})) == v )) // fallback
428 
429 public:
431  template <typename dummy = int> // need to make this a template to enforce deferred instantiation
433  requires requires (alphabet_char_t<alph_t> const a) { { impl(priority_tag<3>{}, a, dummy{}) }; }
435  constexpr bool operator()(alphabet_char_t<alph_t> const a) const noexcept
436  {
437  static_assert(noexcept(impl(priority_tag<3>{}, a)),
438  "Only overloads that are marked noexcept are picked up by seqan3::char_is_valid_for().");
439  static_assert(std::Same<bool, decltype(impl(priority_tag<3>{}, a))>,
440  "The return type of your char_is_valid_for() implementation must be 'bool'.");
441 
442  return impl(priority_tag<3>{}, a);
443  }
444 };
445 
446 } // namespace seqan3::detail::adl::only
447 
448 namespace seqan3
449 {
450 
497 template <typename alph_t>
499  requires requires { { to_char(std::declval<alph_t>()) }; } // to_char() is required by some defs
501 inline constexpr auto char_is_valid_for = detail::adl::only::char_is_valid_for_fn<alph_t>{};
503 } // namespace seqan3
504 
505 // ============================================================================
506 // assign_char_strictly_to()
507 // ============================================================================
508 
510 {
511 
514 struct assign_char_strictly_to_fn
515 {
517  template <typename alph_t>
519  requires requires (alph_t a, seqan3::alphabet_char_t<alph_t> r)
520  {
521  { seqan3::assign_char_to(r, a) } -> alph_t;
522  { seqan3::char_is_valid_for<alph_t>(r) } -> bool;
523  }
525  decltype(auto) operator()(seqan3::alphabet_char_t<alph_t> const r, alph_t & a) const
526  {
527  if (!seqan3::char_is_valid_for<alph_t>(r))
528  throw seqan3::invalid_char_assignment{seqan3::detail::get_display_name_v<alph_t>, r};
529 
530  return seqan3::assign_char_to(r, a);
531  }
532 
534  template <typename alph_t>
536  requires requires (alph_t a, seqan3::alphabet_char_t<alph_t> r)
537  {
538  { seqan3::assign_char_to(r, a) } -> alph_t;
539  { seqan3::char_is_valid_for<alph_t>(r) } -> bool;
540  }
542  auto operator()(seqan3::alphabet_char_t<alph_t> const r, alph_t && a) const
543  {
544  return operator()(r, a); // call above function but return by value
545  }
546 };
547 
548 } // namespace seqan3::detail::adl::only
549 
550 namespace seqan3
551 {
552 
577 inline constexpr auto assign_char_strictly_to = detail::adl::only::assign_char_strictly_to_fn{};
579 } // namespace seqan3
580 
581 // ============================================================================
582 // alphabet_size
583 // ============================================================================
584 
586 {
592 template <typename alph_t,
594  seqan3::is_constexpr_default_constructible_v<remove_cvref_t<alph_t>>,
595  remove_cvref_t<alph_t>,
597 struct alphabet_size_fn
598 {
599 private:
600  SEQAN3_CPO_IMPL(2, (alphabet_size(v) )) // ADL
601  SEQAN3_CPO_IMPL(1, (seqan3::custom::alphabet_size(v) )) // customisation namespace
602  SEQAN3_CPO_IMPL(0, (deferred_type_t<remove_cvref_t<alph_t>, decltype(v)>::alphabet_size )) // member
603 
604 public:
606  template <typename dummy = int> // need to make this a template to enforce deferred instantiation
608  requires requires { { impl(priority_tag<2>{}, s_alph_t{}, dummy{}) }; }
610  constexpr auto operator()() const noexcept
611  {
612  static_assert(noexcept(impl(priority_tag<2>{}, s_alph_t{})),
613  "Only overloads that are marked noexcept are picked up by seqan3::alphabet_size.");
614  static_assert(std::Constructible<size_t, decltype(impl(priority_tag<2>{}, s_alph_t{}))>,
615  "The return type of your alphabet_size implementation must be convertible to size_t.");
616  static_assert(SEQAN3_IS_CONSTEXPR(impl(priority_tag<2>{}, s_alph_t{})),
617  "Only overloads that are marked constexpr are picked up by seqan3::alphabet_size.");
618 
619  return impl(priority_tag<2>{}, s_alph_t{});
620  }
621 };
622 
624 // required to prevent https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89953
625 template <typename alph_t>
626  requires requires { { alphabet_size_fn<alph_t>{} }; }
627 inline constexpr auto alphabet_size_obj = alphabet_size_fn<alph_t>{};
629 
630 } // namespace seqan3::detail::adl::only
631 
632 namespace seqan3
633 {
634 
673 template <typename alph_t>
675  requires requires { { detail::adl::only::alphabet_size_fn<alph_t>{} }; } &&
676  requires { { detail::adl::only::alphabet_size_obj<alph_t>() }; }
678 inline constexpr auto alphabet_size = detail::adl::only::alphabet_size_obj<alph_t>();
679 
680 // ============================================================================
681 // Semialphabet
682 // ============================================================================
683 
723 template <typename t>
725 SEQAN3_CONCEPT Semialphabet =
728  std::is_nothrow_copy_constructible_v<t> &&
729  requires (t v)
730 {
731  requires seqan3::alphabet_size<t> >= 0;
732 
733  { seqan3::to_rank(v) };
734 };
736 
737 // ============================================================================
738 // WritableSemialphabet
739 // ============================================================================
740 
773 template <typename t>
775 SEQAN3_CONCEPT WritableSemialphabet = Semialphabet<t> && requires (t v, alphabet_rank_t<t> r)
776 {
777  { seqan3::assign_rank_to(r, v) };
778 };
780 
781 // ============================================================================
782 // Alphabet
783 // ============================================================================
784 
825 template <typename t>
827 SEQAN3_CONCEPT Alphabet = Semialphabet<t> && requires (t v)
828 {
829  { seqan3::to_char(v) };
830 };
832 
833 // ============================================================================
834 // WritableAlphabet
835 // ============================================================================
836 
872 template <typename t>
874 SEQAN3_CONCEPT WritableAlphabet = Alphabet<t> && WritableSemialphabet<t> && requires (t v, alphabet_char_t<t> c)
875 {
876  { seqan3::assign_char_to(c, v) };
877 
878  { seqan3::char_is_valid_for<t>(c) };
879 };
881 
882 // ============================================================================
883 // serialisation
884 // ============================================================================
885 
905 template <CerealOutputArchive archive_t, Semialphabet alphabet_t>
906 alphabet_rank_t<alphabet_t> CEREAL_SAVE_MINIMAL_FUNCTION_NAME(archive_t const &, alphabet_t const & l)
907 {
908  return to_rank(l);
909 }
910 
924 template <CerealInputArchive archive_t, typename wrapped_alphabet_t>
925 void CEREAL_LOAD_MINIMAL_FUNCTION_NAME(archive_t const &,
926  wrapped_alphabet_t && l,
927  alphabet_rank_t<detail::strip_cereal_wrapper_t<wrapped_alphabet_t>> const & r)
928  requires Semialphabet<detail::strip_cereal_wrapper_t<wrapped_alphabet_t>>
929 {
930  assign_rank_to(r, static_cast<detail::strip_cereal_wrapper_t<wrapped_alphabet_t> &>(l));
931 }
936 } // namespace seqan3
937 
938 namespace seqan3::detail
939 {
940 // ============================================================================
941 // ConstexprSemialphabet
942 // ============================================================================
943 
952 template <typename t>
954 SEQAN3_CONCEPT ConstexprSemialphabet = Semialphabet<t> && requires
955 {
956  // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
958 };
960 
961 // ============================================================================
962 // WritableConstexprSemialphabet
963 // ============================================================================
964 
974 template <typename t>
976 SEQAN3_CONCEPT WritableConstexprSemialphabet = ConstexprSemialphabet<t> && WritableSemialphabet<t> && requires
977 {
978  // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
979  requires SEQAN3_IS_CONSTEXPR(seqan3::assign_rank_to(alphabet_rank_t<t>{}, std::remove_reference_t<t>{}));
980 };
982 
983 // ============================================================================
984 // ConstexprAlphabet
985 // ============================================================================
986 
996 template <typename t>
998 SEQAN3_CONCEPT ConstexprAlphabet = ConstexprSemialphabet<t> && Alphabet<t> && requires
999 {
1000  // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1002 };
1004 
1005 // ============================================================================
1006 // WritableConstexprAlphabet
1007 // ============================================================================
1008 
1020 template <typename t>
1022 SEQAN3_CONCEPT WritableConstexprAlphabet =
1023  ConstexprAlphabet<t> && WritableConstexprSemialphabet<t> && WritableAlphabet<t> && requires
1024 {
1025  // currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
1026  requires SEQAN3_IS_CONSTEXPR(seqan3::assign_char_to(alphabet_char_t<t>{}, std::remove_reference_t<t>{}));
1027  requires SEQAN3_IS_CONSTEXPR(seqan3::char_is_valid_for<t>(alphabet_char_t<t>{}));
1028 };
1030 
1031 } // namespace seqan3::detail
1032 
Exceptions thrown by entities in the alphabet module.
Provides concepts for core language types and relations that don&#39;t have concepts in C++20 (yet)...
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:501
constexpr char_type to_char(char_type const chr) noexcept
Converting char to char is no-op (it will just return the value you pass in).
Definition: char.hpp:79
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition: concept.hpp:207
#define SEQAN3_CPO_IMPL(PRIO, TERM)
A macro that helps defining the overload set of a customisation point.
Definition: customisation_point.hpp:45
constexpr auto to_char
Return the char representation of an alphabet object.
Definition: concept.hpp:285
The basis for seqan3::Alphabet, but requires only rank interface (not char).
Definition: concept.hpp:32
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition: concept.hpp:103
constexpr auto assign_char_strictly_to
Assign a character to an alphabet object, throw if the character is not valid.
Definition: concept.hpp:577
Provides alphabet adaptations for standard uint types.
The main SeqAn3 namespace.
The concept std::CopyConstructible is satisfied if T is an lvalue reference type, or if it is a MoveC...
#define SEQAN3_IS_CONSTEXPR(...)
Returns true if the expression passed to this macro can be evaluated at compile time, false otherwise.
Definition: function.hpp:25
Provides alphabet adaptations for standard char types.
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:112
Provides various type traits for use on functions.
The Concepts library.
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:294
constexpr auto to_rank(char_type const chr) noexcept
Convert char to rank by casting to an unsigned integral type of same size.
Definition: char.hpp:93
Adaptions of concepts from the Cereal library.
Helper utilities for defining customisation point objects.
Definition: aligned_sequence_concept.hpp:35
The std::Constructible concept specifies that a variable of type T can be initialized with the given ...
constexpr char_type & assign_rank_to(decltype(to_rank(char_type{})) const rank, char_type &chr) noexcept
Assigning a rank to a char is the same as assigning it a numeric value.
Definition: char.hpp:123
constexpr auto alphabet_size(char_type const &chr) noexcept
Return the number of values the char type can take.
Definition: char.hpp:65
Provides various type traits on generic types.
constexpr char_type & assign_char_to(char_type const chr2, char_type &chr) noexcept
Assign a char to the char type (same as calling =).
Definition: char.hpp:108
The identity transformation (a TransformationTrait that returns the input).
Definition: type_traits:30
Requires std::EqualityComparable and all remaing comparison operators (<, <=, >, >=).
A namespace for third party and standard library specialisations of SeqAn customisation points...
Definition: char.hpp:47
Provides overloads for std::hash.
constexpr auto assign_char_to
Assign a character to an alphabet object.
Definition: concept.hpp:395
Static reflection for arbitrary types.
The concept std::Same<T, U> is satisfied if and only if T and U denote the same type.
constexpr auto alphabet_size
A type trait that holds the size of a (semi-)alphabet.
Definition: concept.hpp:678
An exception typically thrown by seqan3::Alphabet::assign_char_strict.
Definition: exception.hpp:25