SeqAn3 3.4.0-rc.1
The Modern C++ library for sequence analysis.
Loading...
Searching...
No Matches
seqan3::detail::customisation_point_object< derived_t, max_priority > Struct Template Reference

A CRTP base-class that defines a customisation_point_object (CPO). More...

#include <seqan3/core/detail/customisation_point.hpp>

+ Inheritance diagram for seqan3::detail::customisation_point_object< derived_t, max_priority >:

Public Member Functions

template<typename... args_t, typename derived_type = derived_t>
constexpr auto operator() (args_t &&... args) const noexcept(auto)
 SFINAE-friendly call-operator of this seqan3::detail::customisation_point_object instance.
 

Private Member Functions

constexpr customisation_point_object ()=default
 Defaulted.
 
constexpr customisation_point_object (customisation_point_object &&)=default
 Defaulted.
 
constexpr customisation_point_object (customisation_point_object const &)=default
 Defaulted.
 
constexpr customisation_point_objectoperator= (customisation_point_object &&)=default
 Defaulted.
 
constexpr customisation_point_objectoperator= (customisation_point_object const &)=default
 Defaulted.
 

Private Attributes

friend derived_t
 Allow derived_t to inherit the constructors of this CRTP-class.
 

Detailed Description

template<typename derived_t, unsigned max_priority>
struct seqan3::detail::customisation_point_object< derived_t, max_priority >

A CRTP base-class that defines a customisation_point_object (CPO).

Template Parameters
derived_tCRTP derived type.
max_priorityThe (highest) start priority the CPO overloads will be checked from.

You can define a CPO similar to decltype(std::ranges::begin) that accepts range.begin() (Member) or begin(range) (ADL):

namespace seqan3::detail::adl_only
{
// Poison-pill overload to prevent non-ADL forms of unqualified lookup.
template <typename... args_t>
void begin(args_t...) = delete;
struct begin_cpo : public detail::customisation_point_object<begin_cpo, 1>
{
// Only this class is allowed to import the constructors from base_t. (CRTP safety idiom)
using base_t::base_t;
// range.begin(), member access
template <typename range_t>
requires true // further constraints
static constexpr auto SEQAN3_CPO_OVERLOAD(seqan3::detail::priority_tag<1>, range_t && range)(
/*return*/ std::forward<range_t>(range).begin() /*;*/
);
// begin(range), ADL access
template <typename range_t>
static constexpr auto SEQAN3_CPO_OVERLOAD(seqan3::detail::priority_tag<0>, range_t && range)(
/*return*/ begin(std::forward<range_t>(range)) /*;*/
);
};
} // namespace seqan3::detail::adl_only
#define SEQAN3_CPO_OVERLOAD(...)
A macro that helps to define a seqan3::detail::customisation_point_object.
Definition customisation_point.hpp:104
A CRTP base-class that defines a customisation_point_object (CPO).
Definition customisation_point.hpp:138
A tag that allows controlled overload resolution via implicit base conversion rules.
Definition customisation_point.hpp:29

and instantiate it like std::ranges::begin:

namespace seqan3
{
// CPO is a normal function object that can be called via seqan3::begin(...)
inline constexpr auto begin = detail::adl_only::begin_cpo{};
} // namespace seqan3
The main SeqAn3 namespace.
Definition aligned_sequence_concept.hpp:26

Any type that has a member function with the name "begin" will now work (a real definition of std::ranges::begin would, of course, further constraint the overload):

// seqan3::begin CPO that will call the "begin" member function
static_assert(std::same_as<decltype(seqan3::begin(vec)), decltype(vec.begin())>); // same iterator type
static_assert(noexcept(vec.begin())); // is noexcept
static_assert(noexcept(seqan3::begin(vec)) == noexcept(vec.begin())); // perfect noexcept-forwarding

Furthermore, any unqualified function call "begin":

// seqan3::begin CPO that will call the "begin" function per ADL
other_library::foo foo{};
static_assert(std::same_as<decltype(seqan3::begin(foo)), decltype(begin(foo))>); // same value type
static_assert(!noexcept(begin(foo))); // isn't noexcept
static_assert(noexcept(seqan3::begin(foo)) == noexcept(begin(foo))); // perfect noexcept-forwarding

seqan3::detail::customisation_point_object is designed to be SFINAE friendly:

auto cpo_is_sfinae_friendly(...) -> void;
template <typename range_t>
auto cpo_is_sfinae_friendly(range_t && range) -> decltype(seqan3::begin(range));
// seqan3::begin itself is SFINAE friendly, i.e. no-hard compiler errors, if no cpo overload matches
static_assert(std::same_as<decltype(cpo_is_sfinae_friendly(0)), void>);
static_assert(std::same_as<decltype(cpo_is_sfinae_friendly(vec)), decltype(vec.begin())>);

Member Function Documentation

◆ operator()()

template<typename derived_t , unsigned max_priority>
template<typename... args_t, typename derived_type = derived_t>
constexpr auto seqan3::detail::customisation_point_object< derived_t, max_priority >::operator() ( args_t &&...  args) const
inlineconstexprnoexcept

SFINAE-friendly call-operator of this seqan3::detail::customisation_point_object instance.

This operator implements the actual CPO overload resolution. Overload resolution will try each base class of seqan3::detail::priority_tag<max_priority>, seqan3::detail::priority_tag<max_priority - 1>, ..., seqan3::detail::priority_tag<0> as first argument to derived_t::cpo_overload. That means a high priority in seqan3::detail::priority_tag will be evaluated first and one can define an order which overload should be prioritised if multiple overloads match.

It perfectly forwards the result and noexcept-property of the derived_t::cpo_overload.


The documentation for this struct was generated from the following file:
Hide me