From 1abf2c59dc9555b0d91169e430734fd8b6b49c1b Mon Sep 17 00:00:00 2001
From: Hannes Hauswedell
Date: Thu, 22 Aug 2019 18:12:58 +0200
Subject: [PATCH] [MISC] various fixes related to alphabet CPOs
---
CHANGELOG.md | 4 +
doc/about/customisation/index.md | 14 +-
doc/howto/write_an_alphabet/index.md | 12 +-
include/seqan3/alphabet/adaptation/char.hpp | 128 ++++------
include/seqan3/alphabet/adaptation/uint.hpp | 137 +++++------
include/seqan3/alphabet/cigar/cigar.hpp | 1 +
include/seqan3/alphabet/concept.hpp | 228 +++++++++++-------
.../seqan3/alphabet/nucleotide/concept.hpp | 33 +--
include/seqan3/alphabet/quality/concept.hpp | 71 +++---
include/seqan3/alphabet/structure/concept.hpp | 166 +++++++------
.../seqan3/core/detail/debug_stream_range.hpp | 1 +
.../seqan3/io/sequence_file/format_fasta.hpp | 1 +
.../seqan3/io/sequence_file/format_fastq.hpp | 1 +
.../io/structure_file/format_vienna.hpp | 1 +
test/unit/alphabet/CMakeLists.txt | 1 +
.../composite/alphabet_variant_test.cpp | 1 +
test/unit/alphabet/custom_alphabet3_test.cpp | 81 +++++++
.../alphabet/debug_stream_alphabet_test.cpp | 2 +-
18 files changed, 489 insertions(+), 394 deletions(-)
create mode 100644 test/unit/alphabet/custom_alphabet3_test.cpp
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 55eadc8b17..7a4260f5fa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,6 +29,10 @@ If possible, provide tooling that performs the changes, e.g. a shell-script.
## API changes
+* **Customising for third party types has changes slightly:**
+ You are only affected if you added types to `seqan3::custom::`.
+ Please see [About Customisation](http://docs.seqan.de/seqan/3-master-user/about_customisation.html).
+
#### Argument parser
* **Changed class signature of input/output file validators:**
diff --git a/doc/about/customisation/index.md b/doc/about/customisation/index.md
index 07e4826438..34bc08727b 100644
--- a/doc/about/customisation/index.md
+++ b/doc/about/customisation/index.md
@@ -29,10 +29,16 @@ To customise one of our customisation points, do one of the following:
* Provide functionality as members *or* inside the namespace of your type (will be picked up via
[argument dependent lookup](https://en.cppreference.com/w/cpp/language/adl)).
- * If you adapt a third party's type and you cannot add to that type's namespace, provide functionality inside the
- namespace `seqan3::custom` (this is the "upload namespace").
- * **Never** add names (types, functions, variables...) to namespace `seqan3` and never explicitly specialise one
- of our templates or overload one of our functions.
+ * If you adapt a third party's type and you cannot add to that type's namespace, you can specialise the
+ respective template in `seqan3::custom` for that type and provide the needed functionality as static members of
+ that specialisation (this is an "upload space" for specialisations).
+
+\warning
+**Never** add anything (types, functions, variables...) to namespace `seqan3` and never explicitly specialise one
+of our templates (except those in seqan3::custom) or overload one of our functions.
+
+The \link howto_write_an_alphabet HowTo on creating your own alphabet \endlink provides many examples of how to
+satisfy the requirements of customisation point objects.
More technical background on this topic can be found here:
diff --git a/doc/howto/write_an_alphabet/index.md b/doc/howto/write_an_alphabet/index.md
index 1a2e457408..06451fb98a 100644
--- a/doc/howto/write_an_alphabet/index.md
+++ b/doc/howto/write_an_alphabet/index.md
@@ -135,7 +135,7 @@ your type also model these concepts.
\snippet dna2_alphabet.cpp writable_alphabet
\endsolution
-At this point the seqan3::Alphabet concept should be modelled successfully and even seqan3::WritableAlphabet
+At this point the seqan3::Alphabet concept should be modelled successfully and even seqan3::WritableAlphabet
is fine because we implemented `assign_char` and `char_is_valid`.
\snippet dna2_alphabet.cpp writable_alphabet_concept
@@ -157,6 +157,15 @@ without defining the (in)equality and comparison operators. Opposed to the examp
to model the functionality.
\snippet test/unit/alphabet/custom_alphabet_test.cpp my_alph
+## Adaptation of a third party type {#howto_write_an_alphabet_custom}
+
+This example is similar to the previous one, but assuming that you cannot add anything to the namespace of
+the type that you wish to adapt.
+In that case, you need to specialise the seqan3::custom::alphabet class template and provide the required functionality
+as static members.
+
+\snippet test/unit/alphabet/custom_alphabet3_test.cpp third_party_type
+
## Implementation of a non-default-constructible class
This is an example of a custom alphabet that is not default-constructible and that has a non-default overload for
@@ -174,3 +183,4 @@ from '1', 't' and 'T' for value 1 as well as from '0', 'f' and 'F' for value 0.
\note
You should really make your alphabet types [no-throw-default-constructible](\ref std::is_nothrow_default_constructible)
if you can!
+
diff --git a/include/seqan3/alphabet/adaptation/char.hpp b/include/seqan3/alphabet/adaptation/char.hpp
index 98b387cc81..3d2ebab753 100644
--- a/include/seqan3/alphabet/adaptation/char.hpp
+++ b/include/seqan3/alphabet/adaptation/char.hpp
@@ -27,103 +27,81 @@
#include
+#include
#include
#include
namespace seqan3::detail
{
-//!\addtogroup adaptation
-//!\{
-
//!\brief Whether a type is `char`, `char16_t`, `char32_t` or `wchar_t` (type trait).
-template >
-constexpr bool is_char_adaptation_v = std::Same ||
- std::Same ||
- std::Same ||
- std::Same;
-//!\}
+//!\ingroup adaptation
+template
+constexpr bool is_char_adaptation_v = std::Same ||
+ std::Same ||
+ std::Same ||
+ std::Same;
} // namespace seqan3::detail
namespace seqan3::custom
{
-/*!\name Free function wrappers for the char alphabet adaptation
- * \brief For `char`, `char16_t` and `char32_t` do conversion to/from uint types.
- * \ingroup adaptation
- * \{
- */
-
-/*!\brief Return the number of values the char type can take.
- * \tparam char_type One of `char`, `char16_t`, `char32_t` or `wchar_t`.
- * \param chr The parameters actual value is ignored.
- * \returns The respective sizes (e.g. 256 for `char`).
- */
-template
//!\cond
- requires seqan3::detail::is_char_adaptation_v
+template
+struct alphabet;
//!\endcond
-constexpr auto alphabet_size(char_type const & SEQAN3_DOXYGEN_ONLY(chr)) noexcept
-{
- return detail::min_viable_uint_t>{detail::size_in_values_v};
-}
-/*!\brief Converting char to char is no-op (it will just return the value you pass in).
+/*!\brief Alphabet specific customisations for builtin char types.
* \tparam char_type One of `char`, `char16_t`, `char32_t` or `wchar_t`.
- * \param chr The alphabet letter that you wish to convert to char (no-op).
- * \returns `chr`.
+ * \ingroup adaptation
*/
template
//!\cond
- requires seqan3::detail::is_char_adaptation_v
+ requires detail::is_char_adaptation_v
//!\endcond
-constexpr char_type to_char(char_type const chr) noexcept
+struct alphabet
{
- return chr;
-}
+ //!\brief The number of values the char type can take (e.g. 256 for `char`).
+ static constexpr auto alphabet_size =
+ detail::min_viable_uint_t>{detail::size_in_values_v};
-/*!\brief Convert char to rank by casting to an unsigned integral type of same size.
- * \tparam char_type One of `char`, `char16_t`, `char32_t` or `wchar_t`.
- * \param chr The alphabet letter that you wish to convert to rank.
- * \returns The letter's value in the alphabet's rank type (usually a `uint*_t`).
- */
-template
-//!\cond
- requires seqan3::detail::is_char_adaptation_v
-//!\endcond
-constexpr auto to_rank(char_type const chr) noexcept
-{
- return static_cast<::seqan3::detail::min_viable_uint_t>(chr);
-}
+ /*!\brief Converting char to char is no-op (it will just return the value you pass in).
+ * \param[in] chr The alphabet letter that you wish to convert to char (no-op).
+ * \returns `chr`.
+ */
+ static constexpr char_type to_char(char_type const chr) noexcept
+ {
+ return chr;
+ }
-/*!\brief Assign a char to the char type (same as calling `=`).
- * \tparam char_type One of `char`, `char16_t`, `char32_t` or `wchar_t`.
- * \param chr The alphabet letter that you wish to assign to.
- * \param chr2 The `char` value you wish to assign.
- * \returns A reference to the alphabet letter you passed in.
- */
-template
-//!\cond
- requires detail::is_char_adaptation_v
-//!\endcond
-constexpr char_type & assign_char_to(char_type const chr2, char_type & chr) noexcept
-{
- return chr = chr2;
-}
+ /*!\brief Convert char to rank by casting to an unsigned integral type of same size.
+ * \param[in] chr The alphabet letter that you wish to convert to rank.
+ * \returns The letter's value in the alphabet's rank type (usually a `uint*_t`).
+ */
+ static constexpr auto to_rank(char_type const chr) noexcept
+ {
+ return static_cast>(chr);
+ }
-/*!\brief Assigning a rank to a char is the same as assigning it a numeric value.
- * \tparam char_type One of `char`, `char16_t`, `char32_t` or `wchar_t`.
- * \param chr The alphabet letter that you wish to assign to.
- * \param rank The `rank` value you wish to assign.
- * \returns A reference to the alphabet letter you passed in.
- */
-template
-//!\cond
- requires detail::is_char_adaptation_v
-//!\endcond
-constexpr char_type & assign_rank_to(decltype(to_rank(char_type{})) const rank, char_type & chr) noexcept
-{
- return chr = rank;
-}
-//!\}
+ /*!\brief Assign a char to the char type (same as calling `=`).
+ * \param[in] chr2 The `char` value you wish to assign.
+ * \param[in,out] chr The alphabet letter that you wish to assign to.
+ * \returns A reference to the alphabet letter you passed in.
+ */
+ static constexpr char_type & assign_char_to(char_type const chr2, char_type & chr) noexcept
+ {
+ return chr = chr2;
+ }
+
+ /*!\brief Assigning a rank to a char is the same as assigning it a numeric value.
+ * \param[in] rank The `rank` value you wish to assign.
+ * \param[in,out] chr The alphabet letter that you wish to assign to.
+ * \returns A reference to the alphabet letter you passed in.
+ */
+ static constexpr char_type & assign_rank_to(decltype(alphabet::to_rank(char_type{})) const rank,
+ char_type & chr) noexcept
+ {
+ return chr = rank;
+ }
+};
} // namespace seqan3::custom
diff --git a/include/seqan3/alphabet/adaptation/uint.hpp b/include/seqan3/alphabet/adaptation/uint.hpp
index 96337eba5c..73754b2ad7 100644
--- a/include/seqan3/alphabet/adaptation/uint.hpp
+++ b/include/seqan3/alphabet/adaptation/uint.hpp
@@ -27,107 +27,84 @@
#include
+#include
#include
#include
namespace seqan3::detail
{
-//!\addtogroup adaptation
-//!\{
-
//!\brief Whether a type is `uint8_t`, `uint16_t` or `uint32_t`.
-template >
-constexpr bool is_uint_adaptation_v = std::Same ||
- std::Same ||
- std::Same;
-//!\}
+//!\ingroup adaptation
+template
+constexpr bool is_uint_adaptation_v = std::Same ||
+ std::Same ||
+ std::Same;
} // namespace seqan3::detail
namespace seqan3::custom
{
-/*!\name Free function wrappers for the uint alphabet adaptation
- * \brief For `uint8_t`, `uint16_t` and `uint32_t` do conversion to/from char types.
- * \ingroup adaptation
- * \{
- */
-
-/*!\brief Return the number of values the uint type can take.
- * \tparam uint_type One of `uint8_t`, `uint16_t` or `uint32_t`.
- * \param intgr The parameter's actual value is ignored.
- * \returns The respective size (e.g. 256 for `uint8_t`).
- */
-template
//!\cond
- requires ::seqan3::detail::is_uint_adaptation_v
+template
+struct alphabet;
//!\endcond
-constexpr auto alphabet_size(uint_type const & SEQAN3_DOXYGEN_ONLY(intgr)) noexcept
-{
- return detail::min_viable_uint_t>{detail::size_in_values_v};
-}
-/*!\brief Converting uint to char casts to a character type of same size.
- * \tparam uint_type One of `uint8_t`, `uint16_t` or `uint32_t`.
- * \param intgr The alphabet letter that you wish to convert to char.
- * \returns The letter's value in the alphabet's rank type (usually `uint`).
+/*!\brief Alphabet specific customisations for unsigned integral types.
+ * \tparam uint_type Any of `uint8_t`, `uint16_t` and `uint32_t`.
+ * \ingroup adaptation
*/
template
//!\cond
- requires detail::is_uint_adaptation_v
+ requires seqan3::detail::is_uint_adaptation_v
//!\endcond
-constexpr auto to_char(uint_type const intgr) noexcept
+struct alphabet
{
- if constexpr (std::Same)
- return static_cast(intgr);
- else if constexpr (std::Same)
- return static_cast(intgr);
- else
- return static_cast(intgr);
-}
+ //!\brief Return the number of values the uint type can take (e.g. 256 for `uint8_t`).
+ static constexpr auto alphabet_size =
+ detail::min_viable_uint_t>{detail::size_in_values_v};
-/*!\brief Converting uint to rank is a no-op (it will just return the value you pass in).
- * \tparam uint_type One of `uint8_t`, `uint16_t` or `uint32_t`.
- * \param intgr The alphabet letter that you wish to convert to rank.
- * \returns `intgr`.
- */
-template
-//!\cond
- requires detail::is_uint_adaptation_v
-//!\endcond
-constexpr uint_type to_rank(uint_type const intgr) noexcept
-{
- return intgr;
-}
+ /*!\brief Converting uint to char casts to a character type of same size.
+ * \param[in] intgr The alphabet letter that you wish to convert to char.
+ * \returns The letter's value in the alphabet's rank type (usually `uint`).
+ */
+ static constexpr auto to_char(uint_type const intgr) noexcept
+ {
+ if constexpr (std::Same)
+ return static_cast(intgr);
+ else if constexpr (std::Same)
+ return static_cast(intgr);
+ else
+ return static_cast(intgr);
+ }
-/*!\brief Assign from a character type via implicit or explicit cast.
- * \tparam uint_type One of `uint8_t`, `uint16_t` or `uint32_t`.
- * \param intgr The alphabet letter that you wish to assign to.
- * \param chr The `char` value you wish to assign.
- * \returns A reference to the alphabet letter you passed in.
- */
-template
-//!\cond
- requires detail::is_uint_adaptation_v
-//!\endcond
-constexpr uint_type & assign_char_to(decltype(to_char(uint_type{})) const chr, uint_type & intgr) noexcept
-{
- return intgr = chr;
-}
+ /*!\brief Converting uint to rank is a no-op (it will just return the value you pass in).
+ * \param[in] intgr The alphabet letter that you wish to convert to rank.
+ * \returns `intgr`.
+ */
+ static constexpr uint_type to_rank(uint_type const intgr) noexcept
+ {
+ return intgr;
+ }
-/*!\brief Assign a rank to to the uint (same as calling `=`).
- * \tparam uint_type One of `uint8_t`, `uint16_t` or `uint32_t`.
- * \param intgr The alphabet letter that you wish to assign to.
- * \param intgr2 The `rank` value you wish to assign.
- * \returns A reference to the alphabet letter you passed in.
- */
-template
-//!\cond
- requires detail::is_uint_adaptation_v
-//!\endcond
-constexpr uint_type & assign_rank_to(uint_type const intgr2, uint_type & intgr) noexcept
-{
- return intgr = intgr2;
-}
+ /*!\brief Assign from a character type via implicit or explicit cast.
+ * \param[in] chr The `char` value you wish to assign.
+ * \param[in,out] intgr The alphabet letter that you wish to assign to.
+ * \returns A reference to the alphabet letter you passed in.
+ */
+ static constexpr uint_type & assign_char_to(decltype(to_char(uint_type{})) const chr, uint_type & intgr) noexcept
+ {
+ return intgr = chr;
+ }
+
+ /*!\brief Assign a rank to to the uint (same as calling `=`).
+ * \param[in] intgr2 The `rank` value you wish to assign.
+ * \param[in,out] intgr The alphabet letter that you wish to assign to.
+ * \returns A reference to the alphabet letter you passed in.
+ */
+ static constexpr uint_type & assign_rank_to(uint_type const intgr2, uint_type & intgr) noexcept
+ {
+ return intgr = intgr2;
+ }
+};
-//!\}
} // namespace seqan3::custom
diff --git a/include/seqan3/alphabet/cigar/cigar.hpp b/include/seqan3/alphabet/cigar/cigar.hpp
index ac483525ed..d443f384e1 100644
--- a/include/seqan3/alphabet/cigar/cigar.hpp
+++ b/include/seqan3/alphabet/cigar/cigar.hpp
@@ -12,6 +12,7 @@
#pragma once
+#include
#include
#include
#include
diff --git a/include/seqan3/alphabet/concept.hpp b/include/seqan3/alphabet/concept.hpp
index 9c4e12cf2d..74600795be 100644
--- a/include/seqan3/alphabet/concept.hpp
+++ b/include/seqan3/alphabet/concept.hpp
@@ -12,8 +12,6 @@
#pragma once
-#include
-#include
#include
#include
#include
@@ -23,20 +21,67 @@
#include
#include
+// ============================================================================
+// forwards
+// ============================================================================
+
+namespace seqan3::custom
+{
+
+/*!\brief A type that can be specialised to provide customisation point implementations so that third party types
+ * model alphabet concepts.
+ * \tparam t The type you wish to specialise for.
+ * \ingroup alphabet
+ *
+ * \details
+ *
+ * For examples of when and how you can make use of this type, please see \link about_customisation the page on
+ * customisation \endlink and the \link howto_write_an_alphabet_custom section on third party types \endlink in
+ * the Alphabet HowTo.
+ *
+ * Please note that by default the `t const`, `t &` and `t const &` specialisations of this class inherit the
+ * specialisation for `t` so you usually only need to provide a specialisation for `t`.
+ *
+ * \note Only use this, if you cannot provide respective functions in your namespace.
+ */
+template
+struct alphabet
+{};
+
+//!\cond
+template
+struct alphabet : alphabet
+{};
+
+template
+struct alphabet : alphabet
+{};
+
+template
+struct alphabet : alphabet
+{};
+//!\endcond
+
+} // namespace seqan3::custom
+
// ============================================================================
// to_rank()
// ============================================================================
-namespace seqan3::detail::adl::only
+namespace seqan3::detail::adl_only
{
+//!\brief Poison-pill overload to prevent non-ADL forms of unqualified lookup.
+template
+void to_rank(args_t ...) = delete;
+
//!\brief Functor definition for seqan3::to_rank.
struct to_rank_fn
{
private:
- SEQAN3_CPO_IMPL(2, to_rank(v) ) // ADL
- SEQAN3_CPO_IMPL(1, seqan3::custom::to_rank(v) ) // customisation namespace
- SEQAN3_CPO_IMPL(0, v.to_rank() ) // member
+ SEQAN3_CPO_IMPL(2, seqan3::custom::alphabet::to_rank(v)) // explicit customisation
+ SEQAN3_CPO_IMPL(1, to_rank(v) ) // ADL
+ SEQAN3_CPO_IMPL(0, v.to_rank() ) // member
public:
//!\brief Operator definition.
@@ -55,7 +100,7 @@ struct to_rank_fn
}
};
-} // namespace seqan3::detail::adl::only
+} // namespace seqan3::detail::adl_only
namespace seqan3
{
@@ -75,8 +120,8 @@ namespace seqan3
*
* It acts as a wrapper and looks for three possible implementations (in this order):
*
- * 1. A free function `to_rank(your_type const a)` in the namespace of your type (or as `friend`).
- * 2. A free function `to_rank(your_type const a)` in `namespace seqan3::custom`.
+ * 1. A static member function `to_rank(your_type const a)` of the class `seqan3::custom::alphabet`.
+ * 2. A free function `to_rank(your_type const a)` in the namespace of your type (or as `friend`).
* 3. A member function called `to_rank()`.
*
* Functions are only considered for one of the above cases if they are marked `noexcept` (`constexpr` is not required,
@@ -96,7 +141,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 to_rank = detail::adl::only::to_rank_fn{};
+inline constexpr auto to_rank = detail::adl_only::to_rank_fn{};
//!\}
//!\brief The `rank_type` of the semi-alphabet; defined as the return type of seqan3::to_rank.
@@ -113,17 +158,21 @@ using alphabet_rank_t = decltype(seqan3::to_rank(std::declval
+void assign_rank_to(args_t ...) = delete;
+
//!\brief Functor definition for seqan3::assign_rank_to.
//!\ingroup alphabet
struct assign_rank_to_fn
{
private:
- SEQAN3_CPO_IMPL(2, (assign_rank_to(args..., v) )) // ADL
- SEQAN3_CPO_IMPL(1, (seqan3::custom::assign_rank_to(args..., v) )) // customisation namespace
- SEQAN3_CPO_IMPL(0, (v.assign_rank(args...) )) // member
+ SEQAN3_CPO_IMPL(2, (seqan3::custom::alphabet::assign_rank_to(args..., v))) // explicit customisation
+ SEQAN3_CPO_IMPL(1, (assign_rank_to(args..., v) )) // ADL
+ SEQAN3_CPO_IMPL(0, (v.assign_rank(args...) )) // member
public:
//!\brief Operator definition.
@@ -142,7 +191,7 @@ struct assign_rank_to_fn
}
};
-} // namespace seqan3::detail::adl::only
+} // namespace seqan3::detail::adl_only
namespace seqan3
{
@@ -164,10 +213,10 @@ namespace seqan3
*
* It acts as a wrapper and looks for three possible implementations (in this order):
*
- * 1. A free function `assign_rank_to(rank_type const chr, your_type & a)` in the namespace of your
+ * 1. A static member function `assign_rank_to(rank_type const chr, your_type & a)` of the class
+ * `seqan3::custom::alphabet`.
+ * 2. A free function `assign_rank_to(rank_type const chr, your_type & a)` in the namespace of your
* type (or as `friend`).
- * 2. A free function `assign_rank_to(rank_type const chr, your_type & a)` in
- * `namespace seqan3::custom`.
* 3. A member function called `assign_rank(rank_type const chr)` (not `assign_rank_to`).
*
* Functions are only considered for one of the above cases if they are marked `noexcept` (`constexpr` is not required,
@@ -188,7 +237,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_rank_to = detail::adl::only::assign_rank_to_fn{};
+inline constexpr auto assign_rank_to = detail::adl_only::assign_rank_to_fn{};
//!\}
} // namespace seqan3
@@ -196,16 +245,20 @@ inline constexpr auto assign_rank_to = detail::adl::only::assign_rank_to_fn{};
// to_char()
// ============================================================================
-namespace seqan3::detail::adl::only
+namespace seqan3::detail::adl_only
{
+//!\brief Poison-pill overload to prevent non-ADL forms of unqualified lookup.
+template
+void to_char(args_t ...) = delete;
+
//!\brief Functor definition for seqan3::to_char.
struct to_char_fn
{
private:
- SEQAN3_CPO_IMPL(2, to_char(v) ) // ADL
- SEQAN3_CPO_IMPL(1, seqan3::custom::to_char(v) ) // customisation namespace
- SEQAN3_CPO_IMPL(0, v.to_char() ) // member
+ SEQAN3_CPO_IMPL(2, seqan3::custom::alphabet::to_char(v)) // explicit customisation
+ SEQAN3_CPO_IMPL(1, to_char(v) ) // ADL
+ SEQAN3_CPO_IMPL(0, v.to_char() ) // member
public:
//!\brief Operator definition.
@@ -223,7 +276,7 @@ struct to_char_fn
}
};
-} // namespace seqan3::detail::adl::only
+} // namespace seqan3::detail::adl_only
namespace seqan3
{
@@ -244,8 +297,8 @@ namespace seqan3
*
* It acts as a wrapper and looks for three possible implementations (in this order):
*
+ * 2. A static member function `to_char(your_type const a)` of the class `seqan3::custom::alphabet`.
* 1. A free function `to_char(your_type const a)` in the namespace of your type (or as `friend`).
- * 2. A free function `to_char(your_type const a)` in `namespace seqan3::custom`.
* 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,
@@ -265,7 +318,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 to_char = detail::adl::only::to_char_fn{};
+inline constexpr auto to_char = detail::adl_only::to_char_fn{};
//!\}
//!\brief The `char_type` of the alphabet; defined as the return type of seqan3::to_char.
@@ -282,23 +335,21 @@ using alphabet_char_t = decltype(seqan3::to_char(std::declval
+void assign_char_to(args_t ...) = delete;
+
//!\brief Functor definition for seqan3::assign_char_to.
//!\ingroup alphabet
struct assign_char_to_fn
{
private:
- SEQAN3_CPO_IMPL(2, (assign_char_to(args..., v) )) // ADL
- SEQAN3_CPO_IMPL(1, (seqan3::custom::assign_char_to(args..., v) )) // customisation namespace
- SEQAN3_CPO_IMPL(0, (v.assign_char(args...) )) // member
+ SEQAN3_CPO_IMPL(2, (seqan3::custom::alphabet::assign_char_to(args..., v))) // explicit customisation
+ SEQAN3_CPO_IMPL(1, (assign_char_to(args..., v) )) // ADL
+ SEQAN3_CPO_IMPL(0, (v.assign_char(args...) )) // member
public:
//!\brief Operator definition.
@@ -317,7 +368,7 @@ struct assign_char_to_fn
}
};
-} // namespace seqan3::detail::adl::only
+} // namespace seqan3::detail::adl_only
namespace seqan3
{
@@ -339,10 +390,10 @@ namespace seqan3
*
* It acts as a wrapper and looks for three possible implementations (in this order):
*
- * 1. A free function `assign_char_to(char_type const chr, your_type & a)` in the namespace of your
+ * 1. A static member function `assign_char_to(char_type const chr, your_type & a)`
+ * of the class `seqan3::custom::alphabet`.
+ * 2. A free function `assign_char_to(char_type const chr, your_type & a)` in the namespace of your
* type (or as `friend`).
- * 2. A free function `assign_char_to(char_type const chr, your_type & a)` in
- * `namespace seqan3::custom`.
* 3. A member function called `assign_char(char_type const chr)` (not `assign_char_to`).
*
* Functions are only considered for one of the above cases if they are marked `noexcept` (`constexpr` is not required,
@@ -363,7 +414,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_char_to = detail::adl::only::assign_char_to_fn{};
+inline constexpr auto assign_char_to = detail::adl_only::assign_char_to_fn{};
//!\}
} // namespace seqan3
@@ -371,31 +422,30 @@ inline constexpr auto assign_char_to = detail::adl::only::assign_char_to_fn{};
// char_is_valid_for()
// ============================================================================
-namespace seqan3::custom
+namespace seqan3::detail::adl_only
{
-//!\cond
-void char_is_valid_for(); // forward
-//!\endcond
-} // seqan3::custom
-namespace seqan3::detail::adl::only
-{
+//!\brief Poison-pill overload to prevent non-ADL forms of unqualified lookup.
+template
+void char_is_valid_for(args_t ...) = delete;
+
/*!\brief Functor definition for seqan3::char_is_valid_for.
* \tparam alph_t The alphabet type being queried.
- * \tparam s_alph_t `alph_t` with cvref removed and possibly wrapped in std::type_identity; never user-provide this!
* \ingroup alphabet
*/
-template >,
- remove_cvref_t,
- std::type_identity>>
+template
struct char_is_valid_for_fn
{
private:
- SEQAN3_CPO_IMPL(3, (char_is_valid_for(v, s_alph_t{}) )) // ADL
- SEQAN3_CPO_IMPL(2, (seqan3::custom::char_is_valid_for(v, s_alph_t{}) )) // customisation ns
- SEQAN3_CPO_IMPL(1, (deferred_type_t, decltype(v)>::char_is_valid(v) )) // member
- SEQAN3_CPO_IMPL(0, (to_char(assign_char_to(v, s_alph_t{})) == v )) // fallback
+ //!\brief `alph_t` with cvref removed and possibly wrapped in std::type_identity.
+ using s_alph_t = std::conditional_t>,
+ remove_cvref_t,
+ std::type_identity>;
+
+ SEQAN3_CPO_IMPL(3, (deferred_type_t, decltype(v)>::char_is_valid(v))) // expl. cst.
+ SEQAN3_CPO_IMPL(2, (char_is_valid_for(v, s_alph_t{}) )) // ADL
+ SEQAN3_CPO_IMPL(1, (deferred_type_t, decltype(v)>::char_is_valid(v) )) // member
+ SEQAN3_CPO_IMPL(0, (seqan3::to_char(seqan3::assign_char_to(v, s_alph_t{})) == v )) // fallback
public:
//!\brief Operator definition.
@@ -414,7 +464,7 @@ struct char_is_valid_for_fn
}
};
-} // namespace seqan3::detail::adl::only
+} // namespace seqan3::detail::adl_only
namespace seqan3
{
@@ -437,14 +487,13 @@ namespace seqan3
*
* It acts as a wrapper and looks for three possible implementations (in this order):
*
- * 1. A free function `char_is_valid_for(char_type const chr, your_type const &)` in the namespace of your
+ * 1. A static member function `char_is_valid(char_type const chr)` of the class `seqan3::custom::alphabet`.
+ * 2. A free function `char_is_valid_for(char_type const chr, your_type const &)` in the namespace of your
* type (or as `friend`).
- * 2. A free function `char_is_valid_for(char_type const chr, your_type const &)` in
- * `namespace seqan3::custom`.
* 3. A `static` member function called `char_is_valid(char_type)` (not `char_is_valid_for`).
*
* Functions are only considered for one of the above cases if they are marked `noexcept` (`constexpr` is not required,
- * but recommended) and if the returned type is convertible to `bool`. For 1. and 2. the value of the second argument
+ * but recommended) and if the returned type is convertible to `bool`. For 2. the value of the second argument
* to the function shall be ignored, it is only used to select the function via
* [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl).
*
@@ -454,7 +503,7 @@ namespace seqan3
*
* *Note* that if the alphabet type with cvref removed is not std::is_nothrow_default_constructible, this function
* object will instead look for `char_is_valid_for(char_type const chr, std::type_identity const &)`
- * with the same semantics. In that case the "fallback" above also does not work and you are required to provide
+ * in case 2. In that case the "fallback" above also does not work and you are required to provide
* such an implementation.
*
* ### Example
@@ -470,7 +519,7 @@ template
//!\cond
requires requires { { to_char(std::declval()) }; } // to_char() is required by some defs
//!\endcond
-inline constexpr auto char_is_valid_for = detail::adl::only::char_is_valid_for_fn{};
+inline constexpr auto char_is_valid_for = detail::adl_only::char_is_valid_for_fn{};
//!\}
} // namespace seqan3
@@ -478,7 +527,7 @@ inline constexpr auto char_is_valid_for = detail::adl::only::char_is_valid_for_f
// assign_char_strictly_to()
// ============================================================================
-namespace seqan3::detail::adl::only
+namespace seqan3::detail::adl_only
{
//!\brief Functor definition for seqan3::assign_char_strictly_to.
@@ -517,7 +566,7 @@ struct assign_char_strictly_to_fn
}
};
-} // namespace seqan3::detail::adl::only
+} // namespace seqan3::detail::adl_only
namespace seqan3
{
@@ -546,7 +595,7 @@ namespace seqan3
* \include test/snippet/alphabet/assign_char_strictly_to.cpp
*
*/
-inline constexpr auto assign_char_strictly_to = detail::adl::only::assign_char_strictly_to_fn{};
+inline constexpr auto assign_char_strictly_to = detail::adl_only::assign_char_strictly_to_fn{};
//!\}
} // namespace seqan3
@@ -554,24 +603,30 @@ inline constexpr auto assign_char_strictly_to = detail::adl::only::assign_char_s
// alphabet_size
// ============================================================================
-namespace seqan3::detail::adl::only
+namespace seqan3::detail::adl_only
{
+
+//!\brief Poison-pill overload to prevent non-ADL forms of unqualified lookup.
+template
+void alphabet_size(args_t ...) = delete;
+
/*!\brief Functor definition used indirectly by for seqan3::detail::alphabet_size.
* \tparam alph_t The type being queried.
- * \tparam s_alph_t `alph_t` with cvref removed and possibly wrapped in std::type_identity; never user-provide this!
* \ingroup alphabet
*/
-template > &&
- seqan3::is_constexpr_default_constructible_v>,
- remove_cvref_t,
- std::type_identity>>
+template
struct alphabet_size_fn
{
private:
- SEQAN3_CPO_IMPL(2, (alphabet_size(v) )) // ADL
- SEQAN3_CPO_IMPL(1, (seqan3::custom::alphabet_size(v) )) // customisation namespace
- SEQAN3_CPO_IMPL(0, (deferred_type_t, decltype(v)>::alphabet_size )) // member
+ //!\brief `alph_t` with cvref removed and possibly wrapped in std::type_identity.
+ using s_alph_t = std::conditional_t> &&
+ seqan3::is_constexpr_default_constructible_v>,
+ remove_cvref_t,
+ std::type_identity>;
+
+ SEQAN3_CPO_IMPL(2, (deferred_type_t, decltype(v)>::alphabet_size)) // expl. cst.
+ SEQAN3_CPO_IMPL(1, (alphabet_size(v) )) // ADL
+ SEQAN3_CPO_IMPL(0, (deferred_type_t, decltype(v)>::alphabet_size )) // member
public:
//!\brief Operator definition.
@@ -601,7 +656,7 @@ template
inline constexpr auto alphabet_size_obj = alphabet_size_fn{};
//!\endcond
-} // namespace seqan3::detail::adl::only
+} // namespace seqan3::detail::adl_only
namespace seqan3
{
@@ -616,14 +671,13 @@ namespace seqan3
*
* It is only defined for types that provide one of the following (checked in this order):
*
- * 1. A free function `alphabet_size(your_type const &)` in the namespace of your type (or as `friend`) that
+ * 3. A `static constexpr` data member of `seqan3::custom::alphabet` called `alphabet_size`.
+ * 2. A free function `alphabet_size(your_type const &)` in the namespace of your type (or as `friend`) that
* returns the size.
- * 2. A free function `alphabet_size(your_type const &)` in `namespace seqan3::custom` that returns
- * the size.
- * 3. A `static constexpr` data member called `alphabet_size` that is the size.
+ * 3. A `static constexpr` data member of `your_type` called `alphabet_size`.
*
* Functions are only considered for one of the above cases if they are marked `noexcept` **and** `constexpr` and
- * if the returned type models std::Integral. For 1. and 2. the value of the argument to the function shall be
+ * if the returned type models std::Integral. For 2. the value of the argument to the function shall be
* ignored, the argument is only used to select the function via
* [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl).
*
@@ -631,7 +685,7 @@ namespace seqan3
*
* *Note* that if the (semi-)alphabet type with cvref removed is not std::is_nothrow_default_constructible or not
* seqan3::is_constexpr_default_constructible, this object will instead look for
- * `alphabet_size(std::type_identity const &)` with the same semantics (in cases 1. and 2.).
+ * `alphabet_size(std::type_identity const &)` with the same semantics (in case 2.).
*
* ### Example
*
@@ -647,10 +701,10 @@ namespace seqan3
*/
template
//!\cond
- requires requires { { detail::adl::only::alphabet_size_fn{} }; } &&
- requires { { detail::adl::only::alphabet_size_obj() }; } // ICE workarounds
+ requires requires { { detail::adl_only::alphabet_size_fn{} }; } &&
+ requires { { detail::adl_only::alphabet_size_obj() }; } // ICE workarounds
//!\endcond
-inline constexpr auto alphabet_size = detail::adl::only::alphabet_size_obj();
+inline constexpr auto alphabet_size = detail::adl_only::alphabet_size_obj();
// ============================================================================
// Semialphabet
diff --git a/include/seqan3/alphabet/nucleotide/concept.hpp b/include/seqan3/alphabet/nucleotide/concept.hpp
index 279b882cd2..8213753b59 100644
--- a/include/seqan3/alphabet/nucleotide/concept.hpp
+++ b/include/seqan3/alphabet/nucleotide/concept.hpp
@@ -16,33 +16,24 @@
#include
#include
-// ============================================================================
-// forwards
-// ============================================================================
-
-//!\cond
-namespace seqan3::custom
-{
-
-void complement();
-
-} // namespace seqan3::custom
-//!\endcond
-
// ============================================================================
// complement()
// ============================================================================
-namespace seqan3::detail::adl::only
+namespace seqan3::detail::adl_only
{
+//!\brief Poison-pill overload to prevent non-ADL forms of unqualified lookup.
+template
+void complement(args_t ...) = delete;
+
//!\brief Functor definition for seqan3::complement.
struct complement_fn
{
private:
- SEQAN3_CPO_IMPL(2, complement(v) ) // ADL
- SEQAN3_CPO_IMPL(1, seqan3::custom::complement(v) ) // customisation namespace
- SEQAN3_CPO_IMPL(0, v.complement() ) // member
+ SEQAN3_CPO_IMPL(2, seqan3::custom::alphabet::complement(v)) // explicit customisation
+ SEQAN3_CPO_IMPL(1, complement(v) ) // ADL
+ SEQAN3_CPO_IMPL(0, v.complement() ) // member
public:
//!\brief Operator definition.
@@ -61,7 +52,7 @@ struct complement_fn
}
};
-} // namespace seqan3::detail::adl::only
+} // namespace seqan3::detail::adl_only
namespace seqan3
{
@@ -81,8 +72,8 @@ namespace seqan3
*
* It acts as a wrapper and looks for three possible implementations (in this order):
*
- * 1. A free function `complement(your_type const a)` in the namespace of your type (or as `friend`).
- * 2. A free function `complement(your_type const a)` in `namespace seqan3::custom`.
+ * 1. A static member function `complement(your_type const a)` of the class `seqan3::custom::alphabet`.
+ * 2. A free function `complement(your_type const a)` in the namespace of your type (or as `friend`).
* 3. A member function called `complement()`.
*
* Functions are only considered for one of the above cases if they are marked `noexcept` (`constexpr` is not required,
@@ -99,7 +90,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 complement = detail::adl::only::complement_fn{};
+inline constexpr auto complement = detail::adl_only::complement_fn{};
//!\}
// ============================================================================
diff --git a/include/seqan3/alphabet/quality/concept.hpp b/include/seqan3/alphabet/quality/concept.hpp
index dd2cb1e9e7..b7a2b849d7 100644
--- a/include/seqan3/alphabet/quality/concept.hpp
+++ b/include/seqan3/alphabet/quality/concept.hpp
@@ -15,34 +15,24 @@
#include
-// ============================================================================
-// forwards
-// ============================================================================
-
-//!\cond
-namespace seqan3::custom
-{
-
-void to_phred();
-void assign_phred_to();
-
-} // namespace seqan3::custom
-//!\endcond
-
// ============================================================================
// to_phred()
// ============================================================================
-namespace seqan3::detail::adl::only
+namespace seqan3::detail::adl_only
{
+//!\brief Poison-pill overload to prevent non-ADL forms of unqualified lookup.
+template
+void to_phred(args_t ...) = delete;
+
//!\brief Functor definition for seqan3::to_phred.
struct to_phred_fn
{
private:
- SEQAN3_CPO_IMPL(2, to_phred(v) ) // ADL
- SEQAN3_CPO_IMPL(1, seqan3::custom::to_phred(v) ) // customisation namespace
- SEQAN3_CPO_IMPL(0, v.to_phred() ) // member
+ SEQAN3_CPO_IMPL(2, seqan3::custom::alphabet::to_phred(v)) // explicit customisation
+ SEQAN3_CPO_IMPL(1, to_phred(v) ) // ADL
+ SEQAN3_CPO_IMPL(0, v.to_phred() ) // member
public:
//!\brief Operator definition.
@@ -61,7 +51,7 @@ struct to_phred_fn
}
};
-} // namespace seqan3::detail::adl::only
+} // namespace seqan3::detail::adl_only
namespace seqan3
{
@@ -82,14 +72,12 @@ namespace seqan3
*
* It acts as a wrapper and looks for three possible implementations (in this order):
*
- * 1. A free function `to_phred(your_type const a)` in the namespace of your type (or as `friend`).
- * The function must be marked `noexcept` (`constexpr` is not required, but recommended) and the
- * return type be of the respective phred representation (usually a small integral type).
- * 2. A free function `to_phred(your_type const a)` in `namespace seqan3::custom`.
- * The same restrictions apply as above.
+ * 1. A static member function `to_phred(your_type const a)` of the class `seqan3::custom::alphabet`.
+ * 2. A free function `to_phred(your_type const a)` in the namespace of your type (or as `friend`).
* 3. A member function called `to_phred()`.
- * It must be marked `noexcept` (`constexpr` is not required, but recommended) and the return type be of
- * the respective rank representation.
+ *
+ * Functions are only considered for one of the above cases if they are marked `noexcept` (`constexpr` is not required,
+ * but recommended) and if the returned type is convertible to `size_t`.
*
* Every quality alphabet type must provide one of the above.
*
@@ -98,7 +86,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 to_phred = detail::adl::only::to_phred_fn{};
+inline constexpr auto to_phred = detail::adl_only::to_phred_fn{};
//!\}
/*!\brief The `phred_type` of the alphabet; defined as the return type of seqan3::to_phred.
@@ -116,17 +104,21 @@ using alphabet_phred_t = decltype(seqan3::to_phred(std::declval()
// assign_phred_to()
// ============================================================================
-namespace seqan3::detail::adl::only
+namespace seqan3::detail::adl_only
{
+//!\brief Poison-pill overload to prevent non-ADL forms of unqualified lookup.
+template
+void assign_phred_to(args_t ...) = delete;
+
//!\brief Functor definition for seqan3::assign_phred_to.
//!\ingroup quality
struct assign_phred_to_fn
{
private:
- SEQAN3_CPO_IMPL(2, (assign_phred_to(args..., v) )) // ADL
- SEQAN3_CPO_IMPL(1, (seqan3::custom::assign_phred_to(args..., v) )) // customisation namespace
- SEQAN3_CPO_IMPL(0, (v.assign_phred(args...) )) // member
+ 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.
@@ -157,7 +149,7 @@ struct assign_phred_to_fn
}
};
-} // namespace seqan3::detail::adl::only
+} // namespace seqan3::detail::adl_only
namespace seqan3
{
@@ -177,15 +169,14 @@ namespace seqan3
*
* It acts as a wrapper and looks for three possible implementations (in this order):
*
- * 1. A free function `assign_phred_to(phred_type const chr, your_type & a)` in the namespace of your type
+ * 1. A static member function `assign_phred_to(phred_type const chr, your_type & a)`
+ * of the class `seqan3::custom::alphabet`.
+ * 2. A free function `assign_phred_to(phred_type const chr, your_type & a)` in the namespace of your type
* (or as `friend`).
- * The function must be marked `noexcept` (`constexpr` is not required, but recommended) and the
- * return type be `your_type &`.
- * 2. A free function `assign_phred_to(phred_type const chr, your_type & a)` in
- * `namespace seqan3::custom`. The same restrictions apply as above.
* 3. A member function called `assign_phred(phred_type const chr)` (not `assign_phred_to`).
- * It must be marked `noexcept` (`constexpr` is not required, but recommended) and the return type be
- * `your_type &`.
+ *
+ * Functions are only considered for one of the above cases if they are marked `noexcept` (`constexpr` is not required,
+ * but recommended) and if the returned type is `your_type &`.
*
* Every writable quality alphabet type must provide one of the above. *Note* that temporaries of `your_type`
* are handled by this function object and **do not** require an additional overload.
@@ -195,7 +186,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_fn{};
//!\}
} // namespace seqan3
diff --git a/include/seqan3/alphabet/structure/concept.hpp b/include/seqan3/alphabet/structure/concept.hpp
index 906dea5493..73dc89c21a 100644
--- a/include/seqan3/alphabet/structure/concept.hpp
+++ b/include/seqan3/alphabet/structure/concept.hpp
@@ -18,37 +18,24 @@
#include
#include
-// ============================================================================
-// forwards
-// ============================================================================
-
-//!\cond
-namespace seqan3::custom
-{
-
-void is_pair_open();
-void is_pair_close();
-void is_unpaired();
-void max_pseudoknot_depth();
-void pseudoknot_id();
-
-} // namespace seqan3::custom
-//!\endcond
-
// ============================================================================
// is_pair_open()
// ============================================================================
-namespace seqan3::detail::adl::only
+namespace seqan3::detail::adl_only
{
+//!\brief Poison-pill overload to prevent non-ADL forms of unqualified lookup.
+template
+void is_pair_open(args_t ...) = delete;
+
//!\brief Functor definition for seqan3::is_pair_open.
struct is_pair_open_fn
{
private:
- SEQAN3_CPO_IMPL(2, is_pair_open(v) ) // ADL
- SEQAN3_CPO_IMPL(1, seqan3::custom::is_pair_open(v) ) // customisation namespace
- SEQAN3_CPO_IMPL(0, v.is_pair_open() ) // member
+ SEQAN3_CPO_IMPL(2, seqan3::custom::alphabet::is_pair_open(v)) // explicit customisation
+ SEQAN3_CPO_IMPL(1, is_pair_open(v) ) // ADL
+ SEQAN3_CPO_IMPL(0, v.is_pair_open() ) // member
public:
//!\brief Operator definition.
@@ -67,7 +54,7 @@ struct is_pair_open_fn
}
};
-} // namespace seqan3::detail::adl::only
+} // namespace seqan3::detail::adl_only
namespace seqan3
{
@@ -87,14 +74,12 @@ namespace seqan3
*
* It acts as a wrapper and looks for three possible implementations (in this order):
*
- * 1. A free function `is_pair_open(your_type const a)` in the namespace of your type (or as `friend`).
- * The function must be marked `noexcept` (`constexpr` is not required, but recommended) and the
- * return type be `bool`.
- * 2. A free function `is_pair_open(your_type const a)` in `namespace seqan3::custom`.
- * The same restrictions apply as above.
+ * 1. A static member function `is_pair_open(your_type const a)` of the class `seqan3::custom::alphabet`.
+ * 2. A free function `is_pair_open(your_type const a)` in the namespace of your type (or as `friend`).
* 3. A member function called `is_pair_open()`.
- * It must be marked `noexcept` (`constexpr` is not required, but recommended) and the return type be
- * `bool`.
+ *
+ * Functions are only considered for one of the above cases if they are marked `noexcept` (`constexpr` is not required,
+ * but recommended) and if the returned type is `bool.
*
* Every RNA structure alphabet type must provide one of the above.
*
@@ -107,7 +92,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 is_pair_open = detail::adl::only::is_pair_open_fn{};
+inline constexpr auto is_pair_open = detail::adl_only::is_pair_open_fn{};
//!\}
} // namespace seqan3
@@ -116,16 +101,20 @@ inline constexpr auto is_pair_open = detail::adl::only::is_pair_open_fn{};
// is_pair_close()
// ============================================================================
-namespace seqan3::detail::adl::only
+namespace seqan3::detail::adl_only
{
+//!\brief Poison-pill overload to prevent non-ADL forms of unqualified lookup.
+template
+void is_pair_close(args_t ...) = delete;
+
//!\brief Functor definition for seqan3::is_pair_close.
struct is_pair_close_fn
{
private:
- SEQAN3_CPO_IMPL(2, is_pair_close(v) ) // ADL
- SEQAN3_CPO_IMPL(1, seqan3::custom::is_pair_close(v) ) // customisation namespace
- SEQAN3_CPO_IMPL(0, v.is_pair_close() ) // member
+ SEQAN3_CPO_IMPL(2, seqan3::custom::alphabet::is_pair_close(v)) // explicit customisation
+ SEQAN3_CPO_IMPL(1, is_pair_close(v) ) // ADL
+ SEQAN3_CPO_IMPL(0, v.is_pair_close() ) // member
public:
//!\brief Operator definition.
@@ -144,7 +133,7 @@ struct is_pair_close_fn
}
};
-} // namespace seqan3::detail::adl::only
+} // namespace seqan3::detail::adl_only
namespace seqan3
{
@@ -164,14 +153,12 @@ namespace seqan3
*
* It acts as a wrapper and looks for three possible implementations (in this order):
*
- * 1. A free function `is_pair_close(your_type const a)` in the namespace of your type (or as `friend`).
- * The function must be marked `noexcept` (`constexpr` is not required, but recommended) and the
- * return type be `bool`.
- * 2. A free function `is_pair_close(your_type const a)` in `namespace seqan3::custom`.
- * The same restrictions apply as above.
+ * 1. A static member function `is_pair_close(your_type const a)` of the class `seqan3::custom::alphabet`.
+ * 2. A free function `is_pair_close(your_type const a)` in the namespace of your type (or as `friend`).
* 3. A member function called `is_pair_close()`.
- * It must be marked `noexcept` (`constexpr` is not required, but recommended) and the return type be
- * `bool`.
+ *
+ * Functions are only considered for one of the above cases if they are marked `noexcept` (`constexpr` is not required,
+ * but recommended) and if the returned type is `bool.
*
* Every RNA structure alphabet type must provide one of the above.
*
@@ -184,7 +171,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 is_pair_close = detail::adl::only::is_pair_close_fn{};
+inline constexpr auto is_pair_close = detail::adl_only::is_pair_close_fn{};
//!\}
} // namespace seqan3
@@ -193,16 +180,20 @@ inline constexpr auto is_pair_close = detail::adl::only::is_pair_close_fn{};
// is_unpaired()
// ============================================================================
-namespace seqan3::detail::adl::only
+namespace seqan3::detail::adl_only
{
+//!\brief Poison-pill overload to prevent non-ADL forms of unqualified lookup.
+template
+void is_unpaired(args_t ...) = delete;
+
//!\brief Functor definition for seqan3::is_unpaired.
struct is_unpaired_fn
{
private:
- SEQAN3_CPO_IMPL(2, is_unpaired(v) ) // ADL
- SEQAN3_CPO_IMPL(1, seqan3::custom::is_unpaired(v) ) // customisation namespace
- SEQAN3_CPO_IMPL(0, v.is_unpaired() ) // member
+ SEQAN3_CPO_IMPL(2, seqan3::custom::alphabet::is_unpaired(v)) // explicit customisation
+ SEQAN3_CPO_IMPL(1, is_unpaired(v) ) // ADL
+ SEQAN3_CPO_IMPL(0, v.is_unpaired() ) // member
public:
//!\brief Operator definition.
@@ -221,7 +212,7 @@ struct is_unpaired_fn
}
};
-} // namespace seqan3::detail::adl::only
+} // namespace seqan3::detail::adl_only
namespace seqan3
{
@@ -241,14 +232,12 @@ namespace seqan3
*
* It acts as a wrapper and looks for three possible implementations (in this order):
*
- * 1. A free function `is_unpaired(your_type const a)` in the namespace of your type (or as `friend`).
- * The function must be marked `noexcept` (`constexpr` is not required, but recommended) and the
- * return type be `bool`.
- * 2. A free function `is_unpaired(your_type const a)` in `namespace seqan3::custom`.
- * The same restrictions apply as above.
+ * 1. A static member function `is_unpaired(your_type const a)` of the class `seqan3::custom::alphabet`.
+ * 2. A free function `is_unpaired(your_type const a)` in the namespace of your type (or as `friend`).
* 3. A member function called `is_unpaired()`.
- * It must be marked `noexcept` (`constexpr` is not required, but recommended) and the return type be
- * `bool`.
+ *
+ * Functions are only considered for one of the above cases if they are marked `noexcept` (`constexpr` is not required,
+ * but recommended) and if the returned type is `bool.
*
* Every RNA structure alphabet type must provide one of the above.
*
@@ -261,7 +250,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 is_unpaired = detail::adl::only::is_unpaired_fn{};
+inline constexpr auto is_unpaired = detail::adl_only::is_unpaired_fn{};
//!\}
} // namespace seqan3
@@ -270,9 +259,13 @@ inline constexpr auto is_unpaired = detail::adl::only::is_unpaired_fn{};
// max_pseudoknot_depth
// ============================================================================
-namespace seqan3::detail::adl::only
+namespace seqan3::detail::adl_only
{
+//!\brief Poison-pill overload to prevent non-ADL forms of unqualified lookup.
+template
+void max_pseudoknot_depth(args_t ...) = delete;
+
/*!\brief Functor definition for seqan3::max_pseudoknot_depth.
* \tparam alph_t The type being queried.
* \tparam s_alph_t `alph_t` with cvref removed and possibly wrapped in std::type_identity; never user-provide this!
@@ -286,9 +279,9 @@ template , decltype(v)>::max_pseudoknot_depth )) // member
+ SEQAN3_CPO_IMPL(2, (deferred_type_t, decltype(v)>::max_pseudoknot_depth)) // custom
+ SEQAN3_CPO_IMPL(1, (max_pseudoknot_depth(v) )) // ADL
+ SEQAN3_CPO_IMPL(0, (deferred_type_t, decltype(v)>::max_pseudoknot_depth )) // member
public:
//!\brief Operator definition.
@@ -316,7 +309,7 @@ template
inline constexpr auto max_pseudoknot_depth_obj = max_pseudoknot_depth_fn{};
//!\endcond
-} // namespace seqan3::detail::adl::only
+} // namespace seqan3::detail::adl_only
namespace seqan3
{
@@ -342,13 +335,14 @@ namespace seqan3
*
* It acts as a wrapper and looks for three possible implementations (in this order):
*
- * 1. A free function `max_pseudoknot_depth(your_type const)` in the namespace of your type (or as `friend`).
- * The function must be marked `constexpr` and `noexcept` and the return type must be convertible to `size_t`.
- * The value of the argument to the function shall be ignored, it is only used to select the function via
- * [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl).
- * 2. A free function `max_pseudoknot_depth(your_type const)` in `namespace seqan3::custom`.
- * The same restrictions apply as above.
- * 3. A `static constexpr` data member of a type implicitly convertible to `size_t` called `max_pseudoknot_depth`.
+ * 1. A static member variable `max_pseudoknot_depth` of the class `seqan3::custom::alphabet`.
+ * 2. A free function `max_pseudoknot_depth(your_type const)` in the namespace of your type (or as `friend`).
+ * 3. A static member variable `max_pseudoknot_depth` of the class `your_type`.
+ *
+ * Functions/variables are only considered for one of the above cases if they are marked `noexcept` **and** `constexpr` and
+ * if the returned type is convertible to `size_t`. For 2. the value of the argument to the function shall be
+ * ignored, the argument is only used to select the function via
+ * [argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl).
*
* Every RNA structure alphabet type must provide one of the above.
*
@@ -364,10 +358,10 @@ namespace seqan3
*/
template
//!\cond
- requires requires { { detail::adl::only::max_pseudoknot_depth_fn{} }; } &&
- requires { { detail::adl::only::max_pseudoknot_depth_obj() }; }
+ requires requires { { detail::adl_only::max_pseudoknot_depth_fn{} }; } &&
+ requires { { detail::adl_only::max_pseudoknot_depth_obj() }; }
//!\endcond
-inline constexpr auto max_pseudoknot_depth = detail::adl::only::max_pseudoknot_depth_obj();
+inline constexpr auto max_pseudoknot_depth = detail::adl_only::max_pseudoknot_depth_obj();
} // namespace seqan3
@@ -375,16 +369,20 @@ inline constexpr auto max_pseudoknot_depth = detail::adl::only::max_pseudoknot_d
// pseudoknot_id()
// ============================================================================
-namespace seqan3::detail::adl::only
+namespace seqan3::detail::adl_only
{
+//!\brief Poison-pill overload to prevent non-ADL forms of unqualified lookup.
+template
+void pseudoknot_id(args_t ...) = delete;
+
//!\brief Functor definition for seqan3::pseudoknot_id.
struct pseudoknot_id_fn
{
private:
- SEQAN3_CPO_IMPL(2, pseudoknot_id(v) ) // ADL
- SEQAN3_CPO_IMPL(1, seqan3::custom::pseudoknot_id(v) ) // customisation namespace
- SEQAN3_CPO_IMPL(0, v.pseudoknot_id() ) // member
+ SEQAN3_CPO_IMPL(2, seqan3::custom::alphabet::pseudoknot_id(v)) // explicit customisation
+ SEQAN3_CPO_IMPL(1, pseudoknot_id(v) ) // ADL
+ SEQAN3_CPO_IMPL(0, v.pseudoknot_id() ) // member
public:
//!\brief Operator definition.
@@ -403,7 +401,7 @@ struct pseudoknot_id_fn
}
};
-} // namespace seqan3::detail::adl::only
+} // namespace seqan3::detail::adl_only
namespace seqan3
{
@@ -425,14 +423,12 @@ namespace seqan3
*
* It acts as a wrapper and looks for three possible implementations (in this order):
*
- * 1. A free function `pseudoknot_id(your_type const a)` in the namespace of your type (or as `friend`).
- * The function must be marked `noexcept` (`constexpr` is not required, but recommended) and the
- * return type must be convertible to `size_t`.
- * 2. A free function `pseudoknot_id(your_type const a)` in `namespace seqan3::custom`.
- * The same restrictions apply as above.
- * 3. A member function called `pseudoknot_id()`.
- * It must be marked `noexcept` (`constexpr` is not required, but recommended) and the return type
- * must be convertible to `size_t`.
+ * 1. A static member function `pseudoknot_id(your_type const a)` of the class `seqan3::custom::alphabet`.
+ * 2. A free function `pseudoknot_id(your_type const a)` in the namespace of your type (or as `friend`).
+ * 3. A member function of `your_type` called `pseudoknot_id()`.
+ *
+ * Functions are only considered for one of the above cases if they are marked `noexcept` (`constexpr` is not required,
+ * but recommended) and the return type is convertible to `size_t`.
*
* Every RNA structure alphabet type must provide one of the above.
*
@@ -445,7 +441,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 pseudoknot_id = detail::adl::only::pseudoknot_id_fn{};
+inline constexpr auto pseudoknot_id = detail::adl_only::pseudoknot_id_fn{};
//!\}
} // namespace seqan3
diff --git a/include/seqan3/core/detail/debug_stream_range.hpp b/include/seqan3/core/detail/debug_stream_range.hpp
index 2254b67311..6502fd40d8 100644
--- a/include/seqan3/core/detail/debug_stream_range.hpp
+++ b/include/seqan3/core/detail/debug_stream_range.hpp
@@ -12,6 +12,7 @@
#pragma once
+#include
#include
#include
#include
diff --git a/include/seqan3/io/sequence_file/format_fasta.hpp b/include/seqan3/io/sequence_file/format_fasta.hpp
index 287675ead0..5d35652bfa 100644
--- a/include/seqan3/io/sequence_file/format_fasta.hpp
+++ b/include/seqan3/io/sequence_file/format_fasta.hpp
@@ -18,6 +18,7 @@
#include
#include
+#include
#include
#include
#include
diff --git a/include/seqan3/io/sequence_file/format_fastq.hpp b/include/seqan3/io/sequence_file/format_fastq.hpp
index 5451287a09..ddf8860484 100644
--- a/include/seqan3/io/sequence_file/format_fastq.hpp
+++ b/include/seqan3/io/sequence_file/format_fastq.hpp
@@ -23,6 +23,7 @@
#include
#include
+#include
#include
#include
#include
diff --git a/include/seqan3/io/structure_file/format_vienna.hpp b/include/seqan3/io/structure_file/format_vienna.hpp
index 8c93fe8edc..89238c2ca3 100644
--- a/include/seqan3/io/structure_file/format_vienna.hpp
+++ b/include/seqan3/io/structure_file/format_vienna.hpp
@@ -28,6 +28,7 @@
#include
#include
+#include
#include
#include
#include
diff --git a/test/unit/alphabet/CMakeLists.txt b/test/unit/alphabet/CMakeLists.txt
index e3333482db..5baf56526a 100644
--- a/test/unit/alphabet/CMakeLists.txt
+++ b/test/unit/alphabet/CMakeLists.txt
@@ -3,4 +3,5 @@ seqan3_test(alphabet_cereal_test.cpp)
seqan3_test(alphabet_hash_test.cpp)
seqan3_test(custom_alphabet_test.cpp)
seqan3_test(custom_alphabet2_test.cpp)
+seqan3_test(custom_alphabet3_test.cpp)
seqan3_test(debug_stream_alphabet_test.cpp)
diff --git a/test/unit/alphabet/composite/alphabet_variant_test.cpp b/test/unit/alphabet/composite/alphabet_variant_test.cpp
index dd755e98e4..771a183110 100644
--- a/test/unit/alphabet/composite/alphabet_variant_test.cpp
+++ b/test/unit/alphabet/composite/alphabet_variant_test.cpp
@@ -9,6 +9,7 @@
#include
+#include
#include
#include
#include
diff --git a/test/unit/alphabet/custom_alphabet3_test.cpp b/test/unit/alphabet/custom_alphabet3_test.cpp
new file mode 100644
index 0000000000..25ee65e69e
--- /dev/null
+++ b/test/unit/alphabet/custom_alphabet3_test.cpp
@@ -0,0 +1,81 @@
+// -----------------------------------------------------------------------------------------------------
+// Copyright (c) 2006-2019, Knut Reinert & Freie Universität Berlin
+// Copyright (c) 2016-2019, Knut Reinert & MPI für molekulare Genetik
+// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
+// shipped with this file and also available at: https://github.com/seqan/seqan3/blob/master/LICENSE.md
+// -----------------------------------------------------------------------------------------------------
+
+#include
+
+#include "alphabet_test_template.hpp"
+#include "alphabet_constexpr_test_template.hpp"
+
+// Tests the capabilities of the explicit alphabet customisation
+
+//![third_party_type]
+#include // for size_t
+#include // for seqan3::Alphabet
+
+// this is from some other library:
+namespace third_party_ns
+{
+
+enum class third_party_type
+{
+ ZERO,
+ ONE,
+ TWO
+};
+
+} // namespace third_party_ns
+
+// ------------------------------------------------------------------------------------
+
+// this is in your code (no namespace):
+template <>
+struct seqan3::custom::alphabet
+{
+
+ static constexpr size_t alphabet_size = 3;
+
+ static constexpr size_t to_rank(third_party_ns::third_party_type const a) noexcept
+ {
+ return static_cast(a);
+ }
+
+ static constexpr third_party_ns::third_party_type & assign_rank_to(size_t const r, third_party_ns::third_party_type & a) noexcept
+ {
+ switch (r)
+ {
+ case 0: a = third_party_ns::third_party_type::ZERO; return a;
+ case 1: a = third_party_ns::third_party_type::ONE; return a;
+ default: a = third_party_ns::third_party_type::TWO; return a;
+ }
+ }
+
+ static constexpr char to_char(third_party_ns::third_party_type const a) noexcept
+ {
+ switch (a)
+ {
+ case third_party_ns::third_party_type::ZERO: return '0';
+ case third_party_ns::third_party_type::ONE: return '1';
+ default: return '2';
+ }
+ }
+
+ static constexpr third_party_ns::third_party_type & assign_char_to(char const c, third_party_ns::third_party_type & a) noexcept
+ {
+ switch (c)
+ {
+ case '0': a = third_party_ns::third_party_type::ZERO; return a;
+ case '1': a = third_party_ns::third_party_type::ONE; return a;
+ default: a = third_party_ns::third_party_type::TWO; return a;
+ }
+ }
+};
+
+static_assert(seqan3::Alphabet);
+//![third_party_type]
+
+INSTANTIATE_TYPED_TEST_CASE_P(third_party_type, alphabet, third_party_ns::third_party_type);
+INSTANTIATE_TYPED_TEST_CASE_P(third_party_type, alphabet_constexpr, third_party_ns::third_party_type);
diff --git a/test/unit/alphabet/debug_stream_alphabet_test.cpp b/test/unit/alphabet/debug_stream_alphabet_test.cpp
index 8ed766a608..af37601eb0 100644
--- a/test/unit/alphabet/debug_stream_alphabet_test.cpp
+++ b/test/unit/alphabet/debug_stream_alphabet_test.cpp
@@ -32,5 +32,5 @@ TYPED_TEST(debug_stream_test, alphabet)
o.flush();
EXPECT_EQ(o.str().size(), 1u);
- EXPECT_EQ(to_char(o.str()[0]), 'C');
+ EXPECT_EQ(o.str()[0], 'C');
}