diff --git a/include/seqan3/alphabet/alphabet_base.hpp b/include/seqan3/alphabet/alphabet_base.hpp index afcd561765..e9e660ec84 100644 --- a/include/seqan3/alphabet/alphabet_base.hpp +++ b/include/seqan3/alphabet/alphabet_base.hpp @@ -180,43 +180,37 @@ class alphabet_base //!\brief Checks whether the letters `lhs` and `rhs` are equal. friend constexpr bool operator==(derived_type const lhs, derived_type const rhs) noexcept { - using seqan3::to_rank; - return to_rank(lhs) == to_rank(rhs); + return seqan3::to_rank(lhs) == seqan3::to_rank(rhs); } //!\brief Checks whether the letters `lhs` and `rhs` are unequal. friend constexpr bool operator!=(derived_type const lhs, derived_type const rhs) noexcept { - using seqan3::to_rank; - return to_rank(lhs) != to_rank(rhs); + return seqan3::to_rank(lhs) != seqan3::to_rank(rhs); } //!\brief Checks whether the letter `lhs` is smaller than `rhs`. friend constexpr bool operator<(derived_type const lhs, derived_type const rhs) noexcept { - using seqan3::to_rank; - return to_rank(lhs) < to_rank(rhs); + return seqan3::to_rank(lhs) < seqan3::to_rank(rhs); } //!\brief Checks whether the letter `lhs` is greater than `rhs`. friend constexpr bool operator>(derived_type const lhs, derived_type const rhs) noexcept { - using seqan3::to_rank; - return to_rank(lhs) > to_rank(rhs); + return seqan3::to_rank(lhs) > seqan3::to_rank(rhs); } //!\brief Checks whether the letter `lhs` is smaller than or equal to `rhs`. friend constexpr bool operator<=(derived_type const lhs, derived_type const rhs) noexcept { - using seqan3::to_rank; - return to_rank(lhs) <= to_rank(rhs); + return seqan3::to_rank(lhs) <= seqan3::to_rank(rhs); } //!\brief Checks whether the letter `lhs` is bigger than or equal to `rhs`. friend constexpr bool operator>=(derived_type const lhs, derived_type const rhs) noexcept { - using seqan3::to_rank; - return to_rank(lhs) >= to_rank(rhs); + return seqan3::to_rank(lhs) >= seqan3::to_rank(rhs); } //!\} diff --git a/include/seqan3/alphabet/aminoacid/aminoacid_base.hpp b/include/seqan3/alphabet/aminoacid/aminoacid_base.hpp index 154b29211f..66223b2540 100644 --- a/include/seqan3/alphabet/aminoacid/aminoacid_base.hpp +++ b/include/seqan3/alphabet/aminoacid/aminoacid_base.hpp @@ -71,9 +71,8 @@ class aminoacid_base : public alphabet_base //!\endcond explicit constexpr aminoacid_base(other_aa_type const & other) noexcept { - using seqan3::to_rank; static_cast(*this) = - detail::convert_through_char_representation[to_rank(other)]; + detail::convert_through_char_representation[seqan3::to_rank(other)]; } //!\} diff --git a/include/seqan3/alphabet/cigar/cigar.hpp b/include/seqan3/alphabet/cigar/cigar.hpp index 6341080b27..7301e513a8 100644 --- a/include/seqan3/alphabet/cigar/cigar.hpp +++ b/include/seqan3/alphabet/cigar/cigar.hpp @@ -25,21 +25,22 @@ namespace seqan3 { -/*!\brief The cigar alphabet pairs a counter with a seqan3::cigar_op letter. +/*!\brief The cigar semialphabet pairs a counter with a seqan3::cigar_op letter. * \ingroup cigar - * \implements seqan3::writable_alphabet + * \implements seqan3::writable_semialphabet * \implements seqan3::trivially_copyable * \implements seqan3::standard_layout * \implements std::regular * * \details * - * This alphabet represents a unit in a CIGAR string, typically found in the + * This semialphabet represents a unit in a CIGAR string, typically found in the * SAM and BAM formats. It consists of a number and a seqan3::cigar_op symbol. * - * The "char representation" of this alphabet is a seqan3::small_string. This - * has some implications when using it in code that doesn't expect a range - * of symbols. + * It has a "visual representation", but since this is a string and not a char, + * the type only models seqan3::writable_semialphabet and not + * seqan3::writable_alphabet. + * Members for reading/writing the string are provided. * * To avoid confusion between string and char literal, this alphabet has * no user defined literal operators. Always assign from a pair of @@ -102,8 +103,8 @@ class cigar : public alphabet_tuple_base /*!\name Read functions * \{ */ - //!\brief Return the character representation. - small_string<11> to_char() const noexcept + //!\brief Return the string representation. + small_string<11> to_string() const noexcept { small_string<11> ret{}; // maximum number of digits for uint32_t + 1 char for the cigar_op ret.resize(11); @@ -121,8 +122,8 @@ class cigar : public alphabet_tuple_base /*!\name Write functions * \{ */ - //!\brief Assign from the character representation. - cigar & assign_char(small_string<11> const s) noexcept + //!\brief Assign from the string representation. + cigar & assign_string(small_string<11> const s) noexcept { uint32_t num{}; auto [ ptr, errc ] = std::from_chars(s.data(), s.data() + 10, num); @@ -165,7 +166,7 @@ class cigar : public alphabet_tuple_base template inline debug_stream_type & operator<<(debug_stream_type & s, cigar const c) { - s << to_char(c); + s << c.to_string(); return s; } diff --git a/include/seqan3/alphabet/composite/alphabet_tuple_base.hpp b/include/seqan3/alphabet/composite/alphabet_tuple_base.hpp index 2ea240e5b4..bb09a91944 100644 --- a/include/seqan3/alphabet/composite/alphabet_tuple_base.hpp +++ b/include/seqan3/alphabet/composite/alphabet_tuple_base.hpp @@ -235,18 +235,8 @@ class alphabet_tuple_base : + to_rank() * alphabet_tuple_base::cummulative_alph_sizes[index]); } - /*!\name Associated types - * \{ - */ - using typename base_t::rank_type; - using typename base_t::char_type; - using typename base_t::phred_type; - //!\} - public: //Import from base type: - using base_t::to_rank; - using base_t::alphabet_size; using base_t::operator=; /*!\name Constructors, destructor and assignment @@ -438,8 +428,7 @@ class alphabet_tuple_base : using t = meta::at_c; t val{}; - using seqan3::assign_rank_to; - assign_rank_to(l.to_component_rank(), val); + seqan3::assign_rank_to(l.to_component_rank(), val); return component_proxy{val, l}; } @@ -469,8 +458,7 @@ class alphabet_tuple_base : using t = meta::at_c; t val{}; - using seqan3::assign_rank_to; - assign_rank_to(l.to_component_rank(), val); + seqan3::assign_rank_to(l.to_component_rank(), val); return val; } @@ -610,8 +598,7 @@ class alphabet_tuple_base : template static constexpr rank_type rank_sum_helper(component_types ... components, std::index_sequence const &) noexcept { - using seqan3::to_rank; - return ((to_rank(components) * cummulative_alph_sizes[idx]) + ...); + return ((seqan3::to_rank(components) * cummulative_alph_sizes[idx]) + ...); } }; diff --git a/include/seqan3/alphabet/composite/alphabet_variant.hpp b/include/seqan3/alphabet/composite/alphabet_variant.hpp index 3e2519f9e9..f592a71e54 100644 --- a/include/seqan3/alphabet/composite/alphabet_variant.hpp +++ b/include/seqan3/alphabet/composite/alphabet_variant.hpp @@ -489,8 +489,7 @@ class alphabet_variant : public alphabet_base{}, a) }; requires noexcept(impl(priority_tag<2>{}, a)); + requires builtin_character{}, a))>; } //!\endcond constexpr decltype(auto) operator()(alph_t const a) const noexcept @@ -302,7 +303,7 @@ namespace seqan3 * 3. A member function called `to_char()`. * * Functions are only considered for one of the above cases if they are marked `noexcept` (`constexpr` is not required, - * but recommended). + * but recommended) and if the returned type models seqan3::builtin_character. * * Every alphabet type must provide one of the above. * diff --git a/include/seqan3/alphabet/detail/alphabet_proxy.hpp b/include/seqan3/alphabet/detail/alphabet_proxy.hpp index 1ebea6a0f5..14d3532aed 100644 --- a/include/seqan3/alphabet/detail/alphabet_proxy.hpp +++ b/include/seqan3/alphabet/detail/alphabet_proxy.hpp @@ -7,9 +7,7 @@ /*!\file * \author Hannes Hauswedell - * \brief Free function/type trait wrappers for alphabets with member functions/types. - * - * This shall not need be included manually, just include `alphabet/concept.hpp`. + * \brief Provides seqan3::alphabet_proxy. */ #pragma once @@ -22,85 +20,13 @@ #include #include -#if 0 // this is the alphabet_proxy I want, but GCC won't give me: -#include - -template -class alphabet_proxy : public alphabet_type -{ -public: - using base_t = alphabet_type; - - using base_t::alphabet_size; - using typename base_t::rank_type; - using char_type = detail::transformation_trait_or_t, void>; - using phred_type = detail::transformation_trait_or_t, void>; - - using char_type_virtual = detail::valid_template_spec_or_t; - using phred_type_virtual = detail::valid_template_spec_or_t; - - constexpr alphabet_proxy() : base_t{} {} - constexpr alphabet_proxy(alphabet_proxy const &) = default; - constexpr alphabet_proxy(alphabet_proxy &&) = default; - constexpr alphabet_proxy & operator=(alphabet_proxy const &) = default; - constexpr alphabet_proxy & operator=(alphabet_proxy &&) = default; - ~alphabet_proxy() = default; - - constexpr alphabet_proxy(alphabet_type const a) : - base_t{a} - {} - - constexpr alphabet_proxy & operator=(alphabet_type const & c) noexcept - { - base_t::assign_rank(seqan3::to_rank(c)); - static_cast(*this).on_update(); // <- this invokes the actual proxy behaviour! - return *this; - } - - template - requires std::assignable_from - constexpr alphabet_proxy & operator=(indirect_assignable_type const & c) noexcept - { - alphabet_type a{}; - a = c; - return operator=(a); - } - - constexpr alphabet_proxy & assign_char(char_type_virtual const c) noexcept - requires !std::same_as - { - alphabet_type tmp{}; - using seqan3::assign_char_to; - assign_char_to(c, tmp); - return operator=(tmp); - } - - constexpr alphabet_proxy & assign_rank(alphabet_rank_t const r) noexcept - { - alphabet_type tmp{}; - using seqan3::assign_rank_to; - assign_rank_to(r, tmp); - return operator=(tmp); - } - - constexpr alphabet_proxy & assign_phred(phred_type_virtual const c) noexcept - requires !std::same_as - { - alphabet_type tmp{}; - assign_phred_to(c, tmp); - return operator=(tmp); - } -}; -#endif - -#if 1// this is the one that works for most things, but not all - namespace seqan3 { /*!\brief A CRTP-base that eases the definition of proxy types returned in place of regular alphabets. * \tparam derived_type The CRTP parameter type. - * \tparam alphabet_type The type of the alphabet that this proxy emulates. + * \tparam alphabet_type The type of the alphabet that this proxy emulates; must model at least + * seqan3::writable_semialphabet and std::regular. * \ingroup alphabet * * \details @@ -117,8 +43,7 @@ namespace seqan3 * * This class ensures that the proxy itself also models seqan3::semialphabet, seqan3::alphabet, * seqan3::quality_alphabet, seqan3::nucleotide_alphabet and/or seqan3::aminoacid_alphabet if the emulated type models - * these. This makes sure that function templates which accept the original, also accept the proxy. An exception - * are multi-layered composites of alphabets where the proxy currently does not support access via `get`. + * these. This makes sure that function templates which accept the original, also accept the proxy. * * ### Implementation notes * @@ -128,15 +53,24 @@ namespace seqan3 * See seqan3::bitcompressed_vector or seqan3::alphabet_tuple_base for examples of how this class is used. */ template -class alphabet_proxy : public alphabet_base, - detail::valid_template_spec_or_t> +//!\cond + requires std::regular +//!\endcond +class alphabet_proxy : public + std::conditional_t, + alphabet_type, + alphabet_base, + detail::valid_template_spec_or_t>> { private: //!\brief Type of the base class. - using base_t = alphabet_base, - detail::valid_template_spec_or_t>; + using base_t = + std::conditional_t, + alphabet_type, // inherit from emulated type if possible + alphabet_base, + detail::valid_template_spec_or_t>>; //!\brief Befriend the base type. friend base_t; @@ -147,26 +81,11 @@ class alphabet_proxy : public alphabet_base; -public: - // Import from base: - using base_t::alphabet_size; - using base_t::to_rank; - - /*!\name Member types - * \{ - */ - - //!\brief The type of the rank representation. - using rank_type = alphabet_rank_t; - //!\} - private: - //!\brief Never used, but required for valid definitions. - /*!\name Constructors, destructor and assignment * \{ */ - constexpr alphabet_proxy() noexcept : base_t{} {} //!< Defaulted. + constexpr alphabet_proxy() noexcept = default; //!< Defaulted. constexpr alphabet_proxy(alphabet_proxy const &) = default; //!< Defaulted. constexpr alphabet_proxy(alphabet_proxy &&) = default; //!< Defaulted. constexpr alphabet_proxy & operator=(alphabet_proxy const &) = default; //!< Defaulted. @@ -175,6 +94,18 @@ class alphabet_proxy : public alphabet_base + //!\endcond + : base_t{a} + {} + + //!\brief Construction from the emulated type. + constexpr alphabet_proxy(alphabet_type const a) noexcept + //!\cond + requires !std::is_class_v + //!\endcond + : base_t{} { base_t::assign_rank(seqan3::to_rank(a)); } @@ -182,7 +113,11 @@ class alphabet_proxy : public alphabet_base) + seqan3::assign_rank_to(seqan3::to_rank(c), static_cast(*this)); + else + base_t::assign_rank(seqan3::to_rank(c)); + static_cast(*this).on_update(); // <- this invokes the actual proxy behaviour! return static_cast(*this); } @@ -204,6 +139,9 @@ class alphabet_proxy : public alphabet_base; + /*!\name Write functions * \brief All of these call the emulated type's write functions and then delegate to * the assignment operator which invokes derived behaviour. @@ -247,58 +185,68 @@ class alphabet_proxy : public alphabet_base) + return *this; + else + return assign_rank_to(base_t::to_rank(), alphabet_type{}); + + /* Instead of static_cast'ing to the alphabet_type which also considers the constructors of the alphabet_type, + * we explicitly invoke this operator in various places. + * This prevents errors associated with using alphabet_type's constructors. + * + * This is one of error cases: + * The tuple composite seqan3::qualified returns a component_proxy which inherits from alphabet_proxy_base. + * The qualified alphabet itself inherits from quality_base. + * Now when accessing get<1>(seq_qual_alph) we want to call to_phred at some point because we want the quality, + * therefore the to_phred function from alphabet_proxy is called, but this function did a static_cast to the + * derived type which is calling the constructor from quality_base. Unfortunately now, the generic quality_base + * constructor uses `assign_phred_to(to_phred(other), static_cast(*this))`; (here) which again + * tries to call to_phred of the alphabet_proxy => infinite loop :boom: + */ } //!\brief Implicit conversion to types that the emulated type is convertible to. template //!\cond - requires std::convertible_to + requires (!std::is_class_v) && std::convertible_to //!\endcond constexpr operator other_t() const noexcept { return operator alphabet_type(); } + //!\brief Returns the rank. + constexpr auto to_rank() const noexcept + { + return seqan3::to_rank(operator alphabet_type()); + } + //!\brief Returns the character. constexpr auto to_char() const noexcept //!\cond requires alphabet //!\endcond { - /* (smehringer) Explicit conversion instead of static_cast: - * See explanation in to_phred(). - */ return seqan3::to_char(operator alphabet_type()); } - //!\brief Returns the phred. + //!\brief Returns the phred score. constexpr auto to_phred() const noexcept //!\cond requires quality_alphabet //!\endcond { - using seqan3::to_phred; - /* (smehringer) Explicit conversion instead of static_cast: - * The tuple composite qualified returns a component_proxy which inherits from alphabet_proxy_base. - * The qualified alphabet itself inherits from quality_base. - * Now when accessing get<1>(seq_qual_alph) we want to call to_phred at some point because we want the quality, - * therefore the to_phred function from alphabet_proxy is called, but this function did a static_cast to the - * derived type which is calling the constructor from quality_base. Unfortunately now, the generic quality_base - * constructor uses `assign_phred_to(to_phred(other), static_cast(*this))`; (here) which again - * tries to call to_phred of the alphabet_proxy => infinite loop :boom: - */ - return to_phred(operator alphabet_type()); + return seqan3::to_phred(operator alphabet_type()); } -#if 0 // this currently causes GCC ICE in alphabet_tuple_base test + //!\brief Returns the complement. constexpr alphabet_type complement() const noexcept + //!\cond requires nucleotide_alphabet + //!\endcond { - using seqan3::complement; - return complement(static_cast(*this)); + return seqan3::complement(operator alphabet_type()); } -#endif //!\brief Delegate to the emulated type's validator. static constexpr bool char_is_valid(char_type const c) noexcept @@ -318,16 +266,16 @@ class alphabet_proxy : public alphabet_base friend constexpr auto operator==(derived_type const lhs, t const rhs) noexcept - -> std::enable_if_t && seqan3::detail::weakly_equality_comparable_with, + -> std::enable_if_t && detail::weakly_equality_comparable_with, bool> { - return (static_cast(lhs) == rhs); + return (lhs.operator alphabet_type() == rhs); } //!\brief Allow (in-)equality comparison with types that the emulated type is comparable with. template friend constexpr auto operator==(t const lhs, derived_type const rhs) noexcept - -> std::enable_if_t && seqan3::detail::weakly_equality_comparable_with, + -> std::enable_if_t && detail::weakly_equality_comparable_with, bool> { return (rhs == lhs); @@ -336,7 +284,7 @@ class alphabet_proxy : public alphabet_base friend constexpr auto operator!=(derived_type const lhs, t const rhs) noexcept - -> std::enable_if_t && seqan3::detail::weakly_equality_comparable_with, + -> std::enable_if_t && detail::weakly_equality_comparable_with, bool> { return !(lhs == rhs); @@ -345,7 +293,7 @@ class alphabet_proxy : public alphabet_base friend constexpr auto operator!=(t const lhs, derived_type const rhs) noexcept - -> std::enable_if_t && seqan3::detail::weakly_equality_comparable_with, + -> std::enable_if_t && detail::weakly_equality_comparable_with, bool> { return (rhs != lhs); @@ -353,5 +301,4 @@ class alphabet_proxy : public alphabet_base */ size_t operator()(alphabet_t const character) const noexcept { - using seqan3::to_rank; - return to_rank(character); + return seqan3::to_rank(character); } }; diff --git a/include/seqan3/alphabet/nucleotide/nucleotide_base.hpp b/include/seqan3/alphabet/nucleotide/nucleotide_base.hpp index 3fcfe97fce..8bd92e5e37 100644 --- a/include/seqan3/alphabet/nucleotide/nucleotide_base.hpp +++ b/include/seqan3/alphabet/nucleotide/nucleotide_base.hpp @@ -79,9 +79,8 @@ class nucleotide_base : public alphabet_base //!\endcond explicit constexpr nucleotide_base(other_nucl_type const & other) noexcept { - using seqan3::to_rank; static_cast(*this) = - detail::convert_through_char_representation[to_rank(other)]; + detail::convert_through_char_representation[seqan3::to_rank(other)]; } //!\} diff --git a/include/seqan3/alphabet/quality/qualified.hpp b/include/seqan3/alphabet/quality/qualified.hpp index cc5b4d8bcc..14520488eb 100644 --- a/include/seqan3/alphabet/quality/qualified.hpp +++ b/include/seqan3/alphabet/quality/qualified.hpp @@ -143,8 +143,7 @@ class qualified : constexpr qualified complement() const noexcept requires nucleotide_alphabet { - using seqan3::complement; - return qualified{complement(get<0>(*this)), get<1>(*this)}; + return qualified{seqan3::complement(get<0>(*this)), get<1>(*this)}; } //!\} diff --git a/test/snippet/alphabet/cigar/cigar.cpp b/test/snippet/alphabet/cigar/cigar.cpp index 017a7afdf2..02cebdb999 100644 --- a/test/snippet/alphabet/cigar/cigar.cpp +++ b/test/snippet/alphabet/cigar/cigar.cpp @@ -6,8 +6,8 @@ using seqan3::operator""_cigar_op; int main() { seqan3::cigar c{13, 'M'_cigar_op}; - seqan3::debug_stream << c << std::endl; // "13M" + seqan3::debug_stream << c << '\n'; // "13M" - seqan3::assign_char_to("14X", c); - seqan3::debug_stream << c << std::endl; // "14X" + c.assign_string("14X"); + seqan3::debug_stream << c << '\n'; // "14X" } diff --git a/test/snippet/alphabet/cigar/cigar_op.cpp b/test/snippet/alphabet/cigar/cigar_op.cpp index 3c45380cc7..b04ec935bb 100644 --- a/test/snippet/alphabet/cigar/cigar_op.cpp +++ b/test/snippet/alphabet/cigar/cigar_op.cpp @@ -9,5 +9,5 @@ int main() seqan3::cigar_op match{'M'_cigar_op}; // you can print cigar_op values: - seqan3::debug_stream << match << std::endl; // M + seqan3::debug_stream << match << '\n'; // M } diff --git a/test/unit/alphabet/cigar/cigar_test.cpp b/test/unit/alphabet/cigar/cigar_test.cpp index aeaa08c900..f67f34db21 100644 --- a/test/unit/alphabet/cigar/cigar_test.cpp +++ b/test/unit/alphabet/cigar/cigar_test.cpp @@ -11,36 +11,31 @@ #include "../alphabet_test_template.hpp" #include "../semi_alphabet_test_template.hpp" +#include "../semi_alphabet_constexpr_test_template.hpp" -INSTANTIATE_TYPED_TEST_CASE_P(cigar, alphabet_, cigar); INSTANTIATE_TYPED_TEST_CASE_P(cigar, semi_alphabet_test, cigar); -// note: cigar is not usable in constexpr context. +INSTANTIATE_TYPED_TEST_CASE_P(cigar, semi_alphabet_constexpr, cigar); TEST(cigar, brace_init) { cigar c1{uint32_t{223}, 'M'_cigar_op}; - EXPECT_EQ(c1.to_char(), small_string<11>{"223M"}); + EXPECT_EQ(c1.to_string(), small_string<11>{"223M"}); } -TEST(cigar, to_char) +TEST(cigar, to_string) { cigar c1{}; assign_rank_to(uint32_t{223}, get<0>(c1)); assign_char_to('M', get<1>(c1)); - EXPECT_EQ(c1.to_char(), small_string<11>{"223M"}); + EXPECT_EQ(c1.to_string(), small_string<11>{"223M"}); } -TEST(cigar, assign_char) +TEST(cigar, assign_string) { cigar c1{}; - c1.assign_char("223M"); + c1.assign_string("223M"); EXPECT_EQ(uint32_t{223}, to_rank(get<0>(c1))); - EXPECT_EQ('M', to_char(get<1>(c1))); + EXPECT_EQ('M', get<1>(c1).to_char()); } -TEST(cigar, assign_char_strictly_to) -{ - EXPECT_THROW(assign_char_strictly_to("FOO", cigar{}), invalid_char_assignment); - EXPECT_THROW(assign_char_strictly_to("223MZ", cigar{}), invalid_char_assignment); -} diff --git a/test/unit/alphabet/cigar/debug_stream_cigar_test.cpp b/test/unit/alphabet/cigar/debug_stream_cigar_test.cpp index 5a67d48481..adbbd57b4a 100644 --- a/test/unit/alphabet/cigar/debug_stream_cigar_test.cpp +++ b/test/unit/alphabet/cigar/debug_stream_cigar_test.cpp @@ -17,7 +17,7 @@ TEST(debug_stream_test, cigar) debug_stream_type my_stream{o}; cigar c1{}; - c1.assign_char("223M"); + c1.assign_string("223M"); my_stream << c1; diff --git a/test/unit/alphabet/composite/composite_integration_test.cpp b/test/unit/alphabet/composite/composite_integration_test.cpp index d3a356e5bc..bf72e9ccdd 100644 --- a/test/unit/alphabet/composite/composite_integration_test.cpp +++ b/test/unit/alphabet/composite/composite_integration_test.cpp @@ -333,3 +333,21 @@ TEST(composite, custom_comparison) EXPECT_EQ(t51, (qualified, phred42>{'C'_dna4, phred42{3}})); EXPECT_EQ((qualified{'C'_dna4, phred42{3}}), t51); } + +TEST(composite, get_) +{ + qualified, phred42>, phred42> t51{qualified, phred42>{'C'_dna4, phred42{3}}}; + EXPECT_EQ(get<0>(t51), 'C'_dna4); + EXPECT_EQ(get<0>(get<0>(t51)), 'C'_dna4); + + EXPECT_EQ(get<0>(t51), 'C'_rna4); + EXPECT_EQ(get<0>(get<0>(t51)), 'C'_rna4); + + EXPECT_NE(get<0>(t51), gap{}); + EXPECT_NE(get<0>(get<0>(t51)), gap{}); + + EXPECT_EQ(get<0>(t51), gapped('C'_dna4)); + EXPECT_EQ(get<0>(get<0>(t51)), gapped('C'_dna4)); + + EXPECT_NE(get<0>(t51), phred42{0}); +} diff --git a/test/unit/alphabet/detail/alphabet_proxy_test.cpp b/test/unit/alphabet/detail/alphabet_proxy_test.cpp index a787f90da6..594328f415 100644 --- a/test/unit/alphabet/detail/alphabet_proxy_test.cpp +++ b/test/unit/alphabet/detail/alphabet_proxy_test.cpp @@ -25,7 +25,7 @@ class alphabet_proxy_example : public alphabet_proxy=(my_alph lhs, my_alph rhs) { return lhs.b >= rhs.b; } + constexpr friend bool operator< (my_alph lhs, my_alph rhs) { return lhs.b < rhs.b; } + constexpr friend bool operator> (my_alph lhs, my_alph rhs) { return lhs.b > rhs.b; } +}; + + +constexpr size_t alphabet_size(my_alph const &) noexcept +{ + return 2; +} + +constexpr bool to_rank(my_alph const a) noexcept +{ + return a.b; +} + +constexpr my_alph & assign_rank_to(bool const r, my_alph & a) noexcept +{ + a.b = r; + return a; +} + +constexpr char to_char(my_alph const a) noexcept +{ + if (a.b) + return '1'; + else + return '0'; +} + +constexpr my_alph & assign_char_to(char const c, my_alph & a) noexcept +{ + switch (c) + { + case '0': case 'F': case 'f': a.b = 0; return a; + default: a.b = 1; return a; + } +} + +} // namespace my_namespace + +static_assert(seqan3::alphabet_size == 2); +static_assert(seqan3::semialphabet); +static_assert(seqan3::alphabet); + +class alphabet_proxy_example2 : public alphabet_proxy +{ +private: + using base_t = alphabet_proxy; + friend base_t; + + constexpr void on_update() noexcept + {} + +public: + constexpr alphabet_proxy_example2() noexcept = default; + constexpr alphabet_proxy_example2(alphabet_proxy_example2 const &) = default; + constexpr alphabet_proxy_example2(alphabet_proxy_example2 &&) = default; + constexpr alphabet_proxy_example2 & operator=(alphabet_proxy_example2 const &) = default; + constexpr alphabet_proxy_example2 & operator=(alphabet_proxy_example2 &&) = default; + ~alphabet_proxy_example2() = default; +}; + +INSTANTIATE_TYPED_TEST_CASE_P(alphabet_proxy2, alphabet_, alphabet_proxy_example2); +INSTANTIATE_TYPED_TEST_CASE_P(alphabet_proxy2, alphabet_constexpr, alphabet_proxy_example2);