98 lines
2.6 KiB
C++
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
|