alsk/src/alsk/utility.h

98 lines
2.6 KiB
C++

#ifndef ALSK_ALSK_UTILITY_H
#define ALSK_ALSK_UTILITY_H
#include <functional>
#include <string>
#include <tmp/traits.h>
#include <tmp/pack.h>
namespace alsk {
/**
* @brief Tuple printer of ::size()
*/
namespace impl {
template<std::size_t I, typename T, typename = void> struct TupleElementImpl;
template<std::size_t I, typename... Ts>
struct TupleElementImpl<I, std::tuple<Ts...>, std::enable_if_t<(I < sizeof...(Ts))>> {
using type = typename std::tuple_element<I, std::tuple<Ts...>>::type;
};
template<std::size_t I, typename... Ts>
struct TupleElementImpl<I, std::tuple<Ts...>, std::enable_if_t<(I >= sizeof...(Ts))>> {
using type = void;
};
template<std::size_t I, typename T>
using TupleElement = typename TupleElementImpl<I, T>::type;
template<typename T, typename = void> struct HasSize: std::false_type {};
template<typename T> struct HasSize<T, tmp::void_t<decltype(std::declval<std::decay_t<T>>().size())>>: std::true_type {};
template<std::size_t I, std::size_t N, typename T, typename = void> struct PTuple;
template<std::size_t I, std::size_t N, typename T>
struct PTuple<I, N, T, std::enable_if_t<I != N && not HasSize<TupleElement<I, std::decay_t<T>>>{}>> {
static void print(std::string const& lbl, T const& t) {
PTuple<I+1, N, T>::print(lbl, t);
}
};
template<std::size_t I, std::size_t N, typename T>
struct PTuple<I, N, T, tmp::void_t<std::enable_if_t<I != N && HasSize<TupleElement<I, std::decay_t<T>>>{}>>> {
static void print(std::string const& lbl, T const& t) {
std::printf("%s: %zu\n", lbl.c_str(), std::get<I>(t).size());
PTuple<I+1, N, T>::print(lbl, t);
}
};
template<std::size_t I, typename T>
struct PTuple<I, I, T> {
static void print(std::string const&, T const&) {}
};
}
template<typename... Ts>
void pTuple(std::string const& lbl, std::tuple<Ts...> const& t) {
impl::PTuple<0, sizeof...(Ts), std::tuple<Ts...>>::print(lbl, t);
}
/* TODO: find a place */
struct Less {
template<typename T>
bool operator()(T const& lhs, T const& rhs) const { return lhs < rhs; }
};
template<typename T>
static auto max(T&& value) {
return std::forward<T>(value);
}
template<typename T, typename... Ts, std::enable_if_t<sizeof...(Ts) != 0>* = nullptr>
static constexpr auto max(T const& value, Ts&&... values) noexcept {
auto m = max(std::forward<Ts>(values)...);
return std::max(m, value);
}
/**
* helper to write recursive lambda functions
*/
template<typename F>
struct RecursiveLambda {
F f;
template<typename... Args>
void operator()(Args&&... args) const {
f(std::ref(*this), std::forward<Args>(args)...);
}
};
template<typename F>
static RecursiveLambda<std::decay_t<F>> makeRecursiveLambda(F&& f) {
return {std::forward<F>(f)};
}
}
#endif