-
Notifications
You must be signed in to change notification settings - Fork 58
Refined functions
Type-agnostic comparators à la std::less<>
are handy compared to the old std::less<T>
because they allow to use the same comparator everywhere without having to care about the type that is being compared before comparison time. Since the type is deduced by the function object's operator()
, specifying it by hand is a bit boring and redundant.
However, it is sometimes useful to have the type information prior to the comparison (or projection). For example, a case-insensitive comparison needs to call std::use_facet<std::ctype<CharT>>
to know how to compare the given sequence of characters, which might be an expensive operation (at least according to How to do case-insensitive string comparison by Matt Austern). That call could be performed once prior to the sorting if the comparator knew the character type (char, wchar_t, etc...).
To keep the handiness of type-agnostic comparators, while avoidind performance problems, some comparators and projections in cpp-sort have a refine
method that takes a type template parameter and returns a new function object that takes advantage of the type information (e.g. a typed case_insensitive_less
) makes a single call to std::use_facet<std::ctype<CharT>>
when constructed):
auto typed_compare = compare.refine<T>();
Explicitly calling the refine
method can still be considered bothersome, so sorter_facade
already handles it: if the passed comparison or projection function has a suitable refine
method, this method is automatically called with the value_type
of the passed iterator or container, and the result is passed to the sorter implementation instead of the original type-agnostic function. This allows to keep the terseness of type-agnostic comparison and projection functions while benefiting from the potential optimizations inherent to the type information.
#include <cpp-sort/refined.h>
This small header provides the essential utily needed to used refined comparisons and projection functions: the refined
function template takes a template parameter T
and a function func
, then it returns func.template refine<T>()
if func
has a valid refine
method, and returns func
otherwise.
template<typename T, typename Function>
auto refined(Function&& func)
noexcept(noexcept(/* returned expression */))
-> /* see above */;
Additionally, the type trait refined_t
allows to easily deduce the type of a given comparison or projection function once refined for a given type.
template<typename T, typename Function>
using refined_t = std::remove_cvref_t<
decltype(refined<std::decay_t<T>>(std::declval<Function&>()))
>;
- Home
- Quickstart
- Sorting library
- Comparators and projections
- Miscellaneous utilities
- Tutorials
- Tooling
- Benchmarks
- Changelog
- Original research