You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

92 lines
2.0 KiB

#ifndef _INVOKE_CALLABLE
#define _INVOKE_CALLABLE
#include <type_traits>
#include <concepts>
#include <array> // Only for std::size()
/*
* This file defines the function:
* enumerate(
* Container container,
* Callable callable
* )
* The enumerate function will iterate over all elements in the container
* calling the callable object with as many arguments as possible:
* callable(*it, index, sized)
* callable(*it, index)
* callable(*it)
*/
/*
* Concepts filtering Callable objects by the most arguments
* their operator() takes.
*/
template<class Callable, class T>
concept TriArg =
requires(Callable c, T t, std::size_t n) {
c(t, n, n);
};
template<class Callable, class T>
concept DuoArg =
!TriArg<Callable, T>
&& requires(Callable c, T t, std::size_t n) {
c(t, n);
};
template<class Callable, class T>
concept UniArg =
!TriArg<Callable, T>
&& !DuoArg<Callable, T>
&& requires(Callable c, T t) {
c(t);
};
/*
* Functions invoking Callable with actual arguments.
* Constrained by the n-argument Concepts above.
*/
template<class Callable, class T>
typename std::enable_if< TriArg<Callable, T>, void>::type
invoke_on_callable(Callable c, T elem, std::size_t index, std::size_t size)
{
c(elem, index, size);
}
template<class Callable, class T>
typename std::enable_if< DuoArg<Callable, T>, void >::type
invoke_on_callable(Callable c, T elem, std::size_t index, std::size_t)
{
c(elem, index);
}
template<class Callable, class T>
typename std::enable_if< UniArg<Callable, T>, void >::type
invoke_on_callable(Callable c, T elem, std::size_t, std::size_t)
{
c(elem);
}
/*
* enumerate()
*/
template<class Container, class Callable>
void enumerate(Container const& container, Callable callable)
{
std::size_t i{0};
std::size_t size{ std::size(container) };
for (auto item : container) {
invoke_on_callable(callable, item, i++, size);
}
}
#endif