Comparator adapters (original) (raw)

The comparator adapters below are classes mainly designed to wrap binary predicates and should themselves satisfy the BinaryPredicate named requirement.

All adapters below are composed of two elements:

The optimizations performed by the function templates are of the "unwrapping" kind, with a goal to reduce the nesting of templates in the library and to eventually reduce the overall number of instantiated templates.

auto cmp = std::less{}; auto cmp2 = cppsort::flip(cmp); // cppsort::flip_t<std::less<>> auto cmp3 = cppsort::flip(cmp2); // std::less<>

Those unwrappings are meant to be simple and only intended to work with "well-formed" functions that don't go against simple logic rules. If the passed comparators are too tricky and absolutely need the extra wrapping, then it is advised to use the adapter template classes directly instead of the construction functions.

flip

#include <cpp-sort/comparators/flip.h>

The class template flip_t is a function object which, when called, passes the arguments in reversed order to the Callable it holds with and returns the result. It is named after the flip function from Haskell's Prelude module.

flip_t<F> has the following member functions:

// Construction flip_t() = default; explicit constexpr flip_t(const F& func); explicit constexpr flip_t(F&& func);

// Call with flipped arguments template<typename T1, typename T2> constexpr auto operator()(T1&& x, T2&& y) &/const&/&&/const&& noexcept(noexcept(std::invoke(base(), std::forward(y), std::forward(x)))) -> decltype(std::invoke(base(), std::forward(y), std::forward(x)));

// Retrieve the passed callable constexpr auto base() const -> F;

cppsort::flip takes a Callable f of type F and returns an instance of flip_t<std::decay_t<F>> except in the following cases:

flip_t<F> is transparent when F is transparent.

flip_t<F> is considered branchless when F is considered branchless.

not_fn

#include <cpp-sort/comparators/not_fn.h>

The class template not_fn_t is roughly equivalent to the one returned by std::not_fn, a function object which, when called, returns the negation of the Callable it holds.

not_fn_t<F> has the following member functions:

// Construction not_fn_t() = default; explicit constexpr not_fn_t(const F& func); explicit constexpr not_fn_t(F&& func);

// Call and negate template<typename... Args> constexpr auto operator()(Args&&... args) &/const&/&&/const&& noexcept(noexcept(not std::invoke(base(), std::forward(args)...))) -> decltype(not std::invoke(base(), std::forward(args)...));

// Retrieve the passed callable constexpr auto base() const -> F;

cppsort::not_fn takes a Callable f of type F and returns an instance of not_fn_t<std::decay_t<F>> except in the following cases:

not_fn_t<F> is transparent when F is transparent.

projection_compare

#include <cpp-sort/comparators/projection_compare.h>

The class template projection_compare_t can be used to embed a comparison and a projection in a single comparison object, allowing to provide projection support to algorithms that only support comparisons, such as standard library algorithms prior to C++20. Both the passed comparison and projection functions can be Callable.

It is accompanied by a projection_compare function template to avoid having to pass the template parameters by hand, and to perform a few optimizations.

Example:

// Sort a family from older to younger member std::vector family = { /* ... */ }; std::sort(family.begin(), family.end(), cppsort::projection_compare(std::greater{}, &Person::age));

projection_compare_t<C, P> has the following member functions:

// Construction projection_compare_t() = default; projection_compare_t(C comp, P proj);

// Call template<typename T1, typename T2> constexpr auto operator()(T1&& x, T2&& y) &/const&/&&/const&& noexcept(noexcept(std::invoke(comparison(), std::invoke(projection(), std::forward(x)), std::invoke(projection(), std::forward(y))))) -> decltype(std::invoke(comparison(), std::invoke(projection(), std::forward(x)), std::invoke(projection(), std::forward(y))));

// Retrieve the passed comparison constexpr auto comparison() const -> C;

// Retrieve the passed projection constexpr auto projection() const -> P;

cppsort::projection_compare takes two Callable types C and P and returns an instance of projection_compare_t<std::decay_t<C>, std::decay_t<P>> except in the following cases:

projection_compare_t is transparent when the passed comparison and projection are both transparent.

projection_compare_t is considered branchless when the projection it wraps is considered branchless and the comparison it wraps is considered branchless when called with the result of the projection.