Loading...
Searching...
No Matches
alphabet/concept.hpp
Go to the documentation of this file.
// SPDX-FileCopyrightText: 2006-2025 Knut Reinert & Freie Universität Berlin
// SPDX-FileCopyrightText: 2016-2025 Knut Reinert & MPI für molekulare Genetik
// SPDX-License-Identifier: BSD-3-Clause
#pragma once
#include <type_traits>
#include <seqan3/alphabet/exception.hpp>
#include <seqan3/core/concept/cereal.hpp>
#include <seqan3/core/detail/customisation_point.hpp>
#include <seqan3/utility/concept.hpp>
#include <seqan3/utility/detail/type_name_as_string.hpp>
#include <seqan3/utility/type_traits/basic.hpp>
// ============================================================================
// forwards
// ============================================================================
namespace seqan3::custom
{
template <typename t>
struct alphabet
{};
template <typename t>
struct alphabet<t const> : alphabet<t>
{};
template <typename t>
struct alphabet<t &> : alphabet<t>
{};
template <typename t>
struct alphabet<t const &> : alphabet<t>
{};
} // namespace seqan3::custom
// ============================================================================
// to_rank()
// ============================================================================
namespace seqan3::detail::adl_only
{
template <typename... args_t>
void to_rank(args_t...) = delete;
struct to_rank_cpo : public detail::customisation_point_object<to_rank_cpo, 2>
{
using base_t = detail::customisation_point_object<to_rank_cpo, 2>;
using base_t::base_t;
template <typename alphabet_t>
static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_t && alphabet)(
/*return*/ seqan3::custom::alphabet<alphabet_t>::to_rank(std::forward<alphabet_t>(alphabet)) /*;*/
);
template <typename alphabet_t>
static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_t && alphabet)(
/*return*/ to_rank(std::forward<alphabet_t>(alphabet)) /*;*/
);
template <typename alphabet_t>
static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_t && alphabet)(
/*return*/ std::forward<alphabet_t>(alphabet).to_rank() /*;*/
);
};
} // namespace seqan3::detail::adl_only
namespace seqan3
{
inline constexpr auto to_rank = detail::adl_only::to_rank_cpo{};
template <typename semi_alphabet_type>
requires requires {
{ seqan3::to_rank(std::declval<semi_alphabet_type>()) };
}
using alphabet_rank_t = decltype(seqan3::to_rank(std::declval<semi_alphabet_type>()));
} // namespace seqan3
// ============================================================================
// assign_rank_to()
// ============================================================================
namespace seqan3::detail::adl_only
{
template <typename... args_t>
void assign_rank_to(args_t...) = delete;
struct assign_rank_to_cpo : public detail::customisation_point_object<assign_rank_to_cpo, 2>
{
using base_t = detail::customisation_point_object<assign_rank_to_cpo, 2>;
using base_t::base_t;
template <typename alphabet_t>
static constexpr auto
SEQAN3_CPO_OVERLOAD(priority_tag<2>, seqan3::alphabet_rank_t<alphabet_t> const rank, alphabet_t && alphabet)(
/*return*/ static_cast<alphabet_t>(seqan3::custom::alphabet<alphabet_t>::assign_rank_to(rank, alphabet)) /*;*/
);
template <typename alphabet_t>
static constexpr auto
SEQAN3_CPO_OVERLOAD(priority_tag<1>, seqan3::alphabet_rank_t<alphabet_t> const rank, alphabet_t && alphabet)(
/*return*/ static_cast<alphabet_t>(assign_rank_to(rank, alphabet)) /*;*/
);
template <typename alphabet_t> // least priority
static constexpr auto
SEQAN3_CPO_OVERLOAD(priority_tag<0>, seqan3::alphabet_rank_t<alphabet_t> const rank, alphabet_t && alphabet)(
/*return*/ static_cast<alphabet_t>(std::forward<alphabet_t>(alphabet).assign_rank(rank)) /*;*/
);
};
} // namespace seqan3::detail::adl_only
namespace seqan3
{
inline constexpr auto assign_rank_to = detail::adl_only::assign_rank_to_cpo{};
} // namespace seqan3
// ============================================================================
// to_char()
// ============================================================================
namespace seqan3::detail::adl_only
{
template <typename... args_t>
void to_char(args_t...) = delete;
struct to_char_cpo : public detail::customisation_point_object<to_char_cpo, 2>
{
using base_t = detail::customisation_point_object<to_char_cpo, 2>;
using base_t::base_t;
template <typename alphabet_t>
static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_t && alphabet)(
/*return*/ seqan3::custom::alphabet<alphabet_t>::to_char(std::forward<alphabet_t>(alphabet)) /*;*/
);
template <typename alphabet_t>
static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_t && alphabet)(
/*return*/ to_char(std::forward<alphabet_t>(alphabet)) /*;*/
);
template <typename alphabet_t>
static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_t && alphabet)(
/*return*/ std::forward<alphabet_t>(alphabet).to_char() /*;*/
);
};
} // namespace seqan3::detail::adl_only
namespace seqan3
{
inline constexpr auto to_char = detail::adl_only::to_char_cpo{};
template <typename alphabet_type>
requires requires (alphabet_type const a) {
{ seqan3::to_char(a) };
}
using alphabet_char_t = decltype(seqan3::to_char(std::declval<alphabet_type const>()));
} // namespace seqan3
// ============================================================================
// assign_char_to()
// ============================================================================
namespace seqan3::detail::adl_only
{
template <typename... args_t>
void assign_char_to(args_t...) = delete;
struct assign_char_to_cpo : public detail::customisation_point_object<assign_char_to_cpo, 2>
{
using base_t = detail::customisation_point_object<assign_char_to_cpo, 2>;
using base_t::base_t;
template <typename alphabet_t>
static constexpr auto
SEQAN3_CPO_OVERLOAD(priority_tag<2>, seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet)(
/*return*/ static_cast<alphabet_t>(seqan3::custom::alphabet<alphabet_t>::assign_char_to(chr, alphabet)) /*;*/
);
template <typename alphabet_t>
static constexpr auto
SEQAN3_CPO_OVERLOAD(priority_tag<1>, seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet)(
/*return*/ static_cast<alphabet_t>(assign_char_to(chr, alphabet)) /*;*/
);
template <typename alphabet_t> // least priority
static constexpr auto
SEQAN3_CPO_OVERLOAD(priority_tag<0>, seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet)(
/*return*/ static_cast<alphabet_t>(alphabet.assign_char(chr)) /*;*/
);
};
} // namespace seqan3::detail::adl_only
namespace seqan3
{
inline constexpr auto assign_char_to = detail::adl_only::assign_char_to_cpo{};
} // namespace seqan3
// ============================================================================
// char_is_valid_for()
// ============================================================================
namespace seqan3::detail::adl_only
{
template <typename... args_t>
void char_is_valid_for(args_t...) = delete;
template <typename alphabet_t>
struct char_is_valid_for_cpo : public detail::customisation_point_object<char_is_valid_for_cpo<alphabet_t>, 3>
{
using base_t = detail::customisation_point_object<char_is_valid_for_cpo<alphabet_t>, 3>;
using base_t::base_t;
template <typename alphabet_type>
using alphabet_or_type_identity =
std::conditional_t<std::is_nothrow_default_constructible_v<std::remove_cvref_t<alphabet_type>>,
std::remove_cvref_t<alphabet_type>,
std::type_identity<alphabet_type>>;
template <typename alphabet_type = alphabet_t>
static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<3>, alphabet_char_t<alphabet_type> const chr)(
/*return*/ seqan3::custom::alphabet<alphabet_type>::char_is_valid(chr) == true /*;*/
);
template <typename alphabet_type = alphabet_t>
static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>, alphabet_char_t<alphabet_type> const chr)(
/*return*/ char_is_valid_for(chr, alphabet_or_type_identity<alphabet_type>{}) == true /*;*/
);
template <typename alphabet_type = alphabet_t>
static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>, alphabet_char_t<alphabet_type> const chr)(
/*return*/ std::remove_cvref_t<alphabet_type>::char_is_valid(chr) == true /*;*/
);
template <typename alphabet_type = alphabet_t>
static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>, alphabet_char_t<alphabet_type> const chr)(
/*return*/ seqan3::to_char(seqan3::assign_char_to(chr, alphabet_or_type_identity<alphabet_type>{})) == chr /*;*/
);
};
} // namespace seqan3::detail::adl_only
namespace seqan3
{
template <typename alph_t>
requires requires {
{ to_char(std::declval<alph_t>()) };
} // to_char() is required by some defs
inline constexpr auto char_is_valid_for = detail::adl_only::char_is_valid_for_cpo<alph_t>{};
} // namespace seqan3
// ============================================================================
// assign_char_strictly_to()
// ============================================================================
namespace seqan3::detail::adl_only
{
struct assign_char_strictly_to_fn
{
template <typename alphabet_t>
constexpr decltype(auto) operator()(seqan3::alphabet_char_t<alphabet_t> const chr, alphabet_t && alphabet) const
requires requires () {
{ seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet)) } -> std::convertible_to<alphabet_t>;
{ seqan3::char_is_valid_for<alphabet_t>(chr) } -> std::same_as<bool>;
}
{
if (!seqan3::char_is_valid_for<alphabet_t>(chr))
throw seqan3::invalid_char_assignment{detail::type_name_as_string<alphabet_t>, chr};
return seqan3::assign_char_to(chr, std::forward<alphabet_t>(alphabet));
}
};
} // namespace seqan3::detail::adl_only
namespace seqan3
{
inline constexpr auto assign_char_strictly_to = detail::adl_only::assign_char_strictly_to_fn{};
} // namespace seqan3
// ============================================================================
// alphabet_size
// ============================================================================
namespace seqan3::detail::adl_only
{
template <typename... args_t>
void alphabet_size(args_t...) = delete;
template <typename alphabet_t>
struct alphabet_size_cpo : public detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>
{
using base_t = detail::customisation_point_object<alphabet_size_cpo<alphabet_t>, 2>;
using base_t::base_t;
template <typename alphabet_type>
using alphabet_or_type_identity =
std::conditional_t<std::is_nothrow_default_constructible_v<std::remove_cvref_t<alphabet_type>>
&& seqan3::is_constexpr_default_constructible_v<std::remove_cvref_t<alphabet_type>>,
std::remove_cvref_t<alphabet_type>,
std::type_identity<alphabet_type>>;
template <typename alphabet_type = alphabet_t>
static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<2>)(
/*return*/ seqan3::custom::alphabet<alphabet_type>::alphabet_size /*;*/
);
template <typename alphabet_type = alphabet_t>
static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<1>)(
/*return*/ alphabet_size(alphabet_or_type_identity<alphabet_type>{}) /*;*/
);
template <typename alphabet_type = alphabet_t>
static constexpr auto SEQAN3_CPO_OVERLOAD(priority_tag<0>)(
/*return*/ std::remove_cvref_t<alphabet_type>::alphabet_size /*;*/
);
};
} // namespace seqan3::detail::adl_only
namespace seqan3
{
template <typename alph_t>
requires requires {
{ detail::adl_only::alphabet_size_cpo<alph_t>{}() };
}
inline constexpr auto alphabet_size = detail::adl_only::alphabet_size_cpo<alph_t>{}();
// ============================================================================
// semialphabet
// ============================================================================
template <typename t>
concept semialphabet =
std::totally_ordered<t> && std::copy_constructible<t> && std::is_nothrow_copy_constructible_v<t> && requires (t v) {
{ seqan3::alphabet_size<t> };
{ seqan3::to_rank(v) };
};
// ============================================================================
// writable_semialphabet
// ============================================================================
template <typename t>
concept writable_semialphabet = semialphabet<t> && requires (t v, alphabet_rank_t<t> r) {
{ seqan3::assign_rank_to(r, v) };
};
// ============================================================================
// alphabet
// ============================================================================
template <typename t>
concept alphabet = semialphabet<t> && requires (t v) {
{ seqan3::to_char(v) };
};
// ============================================================================
// writable_alphabet
// ============================================================================
template <typename t>
concept writable_alphabet = alphabet<t> && writable_semialphabet<t> && requires (t v, alphabet_char_t<t> c) {
{ seqan3::assign_char_to(c, v) };
};
// ============================================================================
// serialisation
// ============================================================================
template <cereal_output_archive archive_t, semialphabet alphabet_t>
alphabet_rank_t<alphabet_t> CEREAL_SAVE_MINIMAL_FUNCTION_NAME(archive_t const &, alphabet_t const & l)
{
return to_rank(l);
}
template <cereal_input_archive archive_t, typename wrapped_alphabet_t>
void CEREAL_LOAD_MINIMAL_FUNCTION_NAME(archive_t const &,
wrapped_alphabet_t && l,
alphabet_rank_t<detail::strip_cereal_wrapper_t<wrapped_alphabet_t>> const & r)
requires semialphabet<detail::strip_cereal_wrapper_t<wrapped_alphabet_t>>
{
assign_rank_to(r, static_cast<detail::strip_cereal_wrapper_t<wrapped_alphabet_t> &>(l));
}
} // namespace seqan3
namespace seqan3::detail
{
// ============================================================================
// constexpr_semialphabet
// ============================================================================
template <typename t>
concept constexpr_semialphabet = semialphabet<t> && requires {
// currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
requires SEQAN3_IS_CONSTEXPR(to_rank(std::remove_reference_t<t>{}));
};
// ============================================================================
// writable_constexpr_semialphabet
// ============================================================================
template <typename t>
concept writable_constexpr_semialphabet = constexpr_semialphabet<t> && writable_semialphabet<t> && requires {
// currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
requires SEQAN3_IS_CONSTEXPR(seqan3::assign_rank_to(alphabet_rank_t<t>{}, std::remove_reference_t<t>{}));
};
// ============================================================================
// constexpr_alphabet
// ============================================================================
template <typename t>
concept constexpr_alphabet = constexpr_semialphabet<t> && alphabet<t> && requires {
// currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
requires SEQAN3_IS_CONSTEXPR(to_char(std::remove_reference_t<t>{}));
};
// ============================================================================
// writable_constexpr_alphabet
// ============================================================================
template <typename t>
concept writable_constexpr_alphabet =
constexpr_alphabet<t> && writable_constexpr_semialphabet<t> && writable_alphabet<t> && requires {
// currently only tests rvalue interfaces, because we have no constexpr values in this scope to get references to
requires SEQAN3_IS_CONSTEXPR(seqan3::assign_char_to(alphabet_char_t<t>{}, std::remove_reference_t<t>{}));
};
} // namespace seqan3::detail
exception.hpp
Exceptions thrown by entities in the alphabet module.
basic.hpp
Provides various type traits on generic types.
cereal.hpp
Adaptions of concepts from the Cereal library.
customisation_point.hpp
Helper utilities for defining customisation point objects (CPOs).
SEQAN3_CPO_OVERLOAD
#define SEQAN3_CPO_OVERLOAD(...)
A macro that helps to define a seqan3::detail::customisation_point_object.
Definition customisation_point.hpp:106
std::declval
T declval(T... args)
std::forward
T forward(T... args)
seqan3::assign_char_to
constexpr auto assign_char_to
Assign a character to an alphabet object.
Definition alphabet/concept.hpp:517
seqan3::to_char
constexpr auto to_char
Return the char representation of an alphabet object.
Definition alphabet/concept.hpp:381
seqan3::alphabet_size
constexpr auto alphabet_size
A type trait that holds the size of a (semi-)alphabet.
Definition alphabet/concept.hpp:834
seqan3::alphabet_char_t
decltype(seqan3::to_char(std::declval< alphabet_type const >())) alphabet_char_t
The char_type of the alphabet; defined as the return type of seqan3::to_char.
Definition alphabet/concept.hpp:393
seqan3::assign_rank_to
constexpr auto assign_rank_to
Assign a rank to an alphabet object.
Definition alphabet/concept.hpp:288
seqan3::alphabet_rank_t
decltype(seqan3::to_rank(std::declval< semi_alphabet_type >())) alphabet_rank_t
The rank_type of the semi-alphabet; defined as the return type of seqan3::to_rank....
Definition alphabet/concept.hpp:164
seqan3::char_is_valid_for
constexpr auto char_is_valid_for
Returns whether a character is in the valid set of a seqan3::alphabet (usually implies a bijective ma...
Definition alphabet/concept.hpp:661
seqan3::assign_char_strictly_to
constexpr auto assign_char_strictly_to
Assign a character to an alphabet object, throw if the character is not valid.
Definition alphabet/concept.hpp:721
seqan3::to_rank
constexpr auto to_rank
Return the rank representation of a (semi-)alphabet object.
Definition alphabet/concept.hpp:152
alphabet
The generic alphabet concept that covers most data types used in ranges.
semialphabet
The basis for seqan3::alphabet, but requires only rank interface (not char).
writable_alphabet
Refines seqan3::alphabet and adds assignability.
writable_semialphabet
A refinement of seqan3::semialphabet that adds assignability.
std::is_nothrow_copy_constructible_v
T is_nothrow_copy_constructible_v
seqan3::custom
A namespace for third party and standard library specialisations of SeqAn customisation points.
Definition char.hpp:40
seqan3
The main SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26
seqan3::custom::alphabet
A type that can be specialised to provide customisation point implementations so that third party typ...
Definition alphabet/concept.hpp:46
type_name_as_string.hpp
Provides traits to inspect some information of a type, for example its name.
type_traits
concept.hpp
Provides concepts that do not have equivalents in C++20.
Hide me