From 33d83c0b7193b5c8ac418db671a32662ce0909f0 Mon Sep 17 00:00:00 2001 From: marehr Date: Sun, 14 Mar 2021 14:32:16 +0100 Subject: [PATCH] [MISC] use new CPO-way to define seqan3::assign_phred_to --- include/seqan3/alphabet/quality/concept.hpp | 103 +++++++++++++------- 1 file changed, 68 insertions(+), 35 deletions(-) diff --git a/include/seqan3/alphabet/quality/concept.hpp b/include/seqan3/alphabet/quality/concept.hpp index 3a058929b3..8ed7cec40f 100644 --- a/include/seqan3/alphabet/quality/concept.hpp +++ b/include/seqan3/alphabet/quality/concept.hpp @@ -111,42 +111,75 @@ namespace seqan3::detail::adl_only template void assign_phred_to(args_t ...) = delete; -//!\brief Functor definition for seqan3::assign_phred_to. +//!\brief seqan3::detail::customisation_point_object (CPO) definition for seqan3::assign_phred_to. //!\ingroup quality -struct assign_phred_to_fn +struct assign_phred_to_cpo : public detail::customisation_point_object { -public: - SEQAN3_CPO_IMPL(2, (seqan3::custom::alphabet::assign_phred_to(args..., v))) // explicit customisation - SEQAN3_CPO_IMPL(1, (assign_phred_to(args..., v) )) // ADL - SEQAN3_CPO_IMPL(0, (v.assign_phred(args...) )) // member - -public: - //!\brief Operator definition for lvalues. - template - //!\cond - requires requires (seqan3::alphabet_phred_t const p, alph_t & a) - { { impl(priority_tag<2>{}, a, p) }; } - //!\endcond - constexpr alph_t & operator()(seqan3::alphabet_phred_t const p, alph_t & a) const noexcept - { - static_assert(noexcept(impl(priority_tag<2>{}, a, p)), - "Only overloads that are marked noexcept are picked up by seqan3::assign_phred_to()."); - static_assert(std::same_as{}, a, p))>, - "The return type of your assign_phred_to() implementation must be 'alph_t &'."); - - return impl(priority_tag<2>{}, a, p); - } - - //!\brief Operator definition for rvalues. - template - //!\cond - requires requires (seqan3::alphabet_phred_t const p, alph_t & a) - { { impl(priority_tag<2>{}, a, p) }; } && (!std::is_lvalue_reference_v) - //!\endcond - constexpr alph_t operator()(seqan3::alphabet_phred_t const p, alph_t && a) const noexcept - { - return (*this)(p, a); // call above function but return by value - } + //!\brief CRTP base class seqan3::detail::customisation_point_object. + using base_t = detail::customisation_point_object; + //!\brief Only this class is allowed to import the constructors from #base_t. (CRTP safety idiom) + using base_t::base_t; + + /*!\brief CPO overload (1. out of 3 checks): explicit customisation via `seqan3::custom::alphabet` + * \tparam alphabet_t The type of the alphabet. + * \param phred The Phred to assign the alphabet to. + * \param alphabet The alphabet the Phred is assigned to. + * + * \details + * + * We don't perfect-forward `alphabet` when calling `assign_phred_to(phred, alphabet)`, because we assume that the + * static member function is only defined for lvalue-references. + * + * We static_cast (instead of std::forward) the result of the CPO overload expression, since we want to + * return an explicit copy of it if the forwarding reference of the alphabet is a rvalue-reference. + */ + template + static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, + seqan3::alphabet_phred_t const phred, + alphabet_t && alphabet) + ( + /*return*/ static_cast(seqan3::custom::alphabet::assign_phred_to(phred, alphabet)) /*;*/ + ); + + /*!\brief CPO overload (2. out of 3 checks): argument dependent lookup (ADL), i.e. + * `assign_phred_to(phred, alphabet)` + * \tparam alphabet_t The type of the alphabet. + * \param phred The Phred to assign the alphabet to. + * \param alphabet The alphabet the Phred is assigned to. + * + * \details + * + * We don't perfect-forward `alphabet` when calling `assign_phred_to(phred, alphabet)`, because we assume that the + * ADL function is only defined for lvalue-references. + * + * We static_cast (instead of std::forward) the result of the CPO overload expression, since we want to + * return an explicit copy of it if the forwarding reference of the alphabet is a rvalue-reference. + */ + template + static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, + seqan3::alphabet_phred_t const phred, + alphabet_t && alphabet) + ( + /*return*/ static_cast(assign_phred_to(phred, alphabet)) /*;*/ + ); + + /*!\brief CPO overload (3. out of 3 checks): member access, i.e. `alphabet.assign_phred(phred)` + * \tparam alphabet_t The type of the alphabet. + * \param phred The Phred to assign the alphabet to. + * \param alphabet The alphabet the Phred is assigned to. + * + * \details + * + * We static_cast (instead of std::forward) the result of the CPO overload expression, since we want to + * return an explicit copy of it if the forwarding reference of the alphabet is a rvalue-reference. + */ + template + static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, + seqan3::alphabet_phred_t const phred, + alphabet_t && alphabet) + ( + /*return*/ static_cast(alphabet.assign_phred(phred)) /*;*/ + ); }; } // namespace seqan3::detail::adl_only @@ -186,7 +219,7 @@ namespace seqan3 * This is a customisation point (see \ref about_customisation). To specify the behaviour for your own alphabet type, * simply provide one of the three functions specified above. */ -inline constexpr auto assign_phred_to = detail::adl_only::assign_phred_to_fn{}; +inline constexpr auto assign_phred_to = detail::adl_only::assign_phred_to_cpo{}; //!\} } // namespace seqan3