99 lines
2.9 KiB
C++
99 lines
2.9 KiB
C++
#pragma once
|
|
|
|
#include <cstdint>
|
|
#include <string>
|
|
|
|
namespace sp {
|
|
|
|
/// @brief Concat multiple tuples in one big tuple
|
|
/// @tparam ...input_t Multiple std::tuple types to concat
|
|
template <typename... input_t>
|
|
using tuple_cat_t = decltype(std::tuple_cat(std::declval<input_t>()...));
|
|
|
|
namespace details {
|
|
|
|
template <std::size_t TRem>
|
|
class TupleForEachHelper {
|
|
public:
|
|
template <typename TTuple, typename TFunc>
|
|
static void Exec(TTuple&& tuple, TFunc&& func) {
|
|
using Tuple = typename std::decay<TTuple>::type;
|
|
static const std::size_t TupleSize = std::tuple_size<Tuple>::value;
|
|
static_assert(TRem <= TupleSize, "Incorrect parameters");
|
|
|
|
// Invoke function with current element
|
|
static const std::size_t Idx = TupleSize - TRem;
|
|
func(std::get<Idx>(std::forward<TTuple>(tuple)));
|
|
|
|
// Compile time recursion - invoke function with the remaining elements
|
|
TupleForEachHelper<TRem - 1>::Exec(std::forward<TTuple>(tuple), std::forward<TFunc>(func));
|
|
}
|
|
};
|
|
|
|
template <>
|
|
class TupleForEachHelper<0> {
|
|
public:
|
|
// Stop compile time recursion
|
|
template <typename TTuple, typename TFunc>
|
|
static void Exec(TTuple&& tuple, TFunc&& func) {
|
|
static_cast<void>(tuple);
|
|
static_cast<void>(func);
|
|
}
|
|
};
|
|
|
|
} // namespace details
|
|
|
|
template <typename TFunc, typename TTuple>
|
|
void TupleForEach(TFunc&& func, TTuple&& tuple) {
|
|
using Tuple = typename std::decay<TTuple>::type;
|
|
static const std::size_t TupleSize = std::tuple_size<Tuple>::value;
|
|
|
|
details::TupleForEachHelper<TupleSize>::Exec(std::forward<TTuple>(tuple), std::forward<TFunc>(func));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace details {
|
|
|
|
template <typename T, typename U = void>
|
|
struct is_mappish_impl : std::false_type {};
|
|
|
|
template <typename T>
|
|
struct is_mappish_impl<T, std::void_t<typename T::key_type, typename T::mapped_type,
|
|
decltype(std::declval<T&>()[std::declval<const typename T::key_type&>()])>> : std::true_type {};
|
|
|
|
template <typename T, typename U = void>
|
|
struct is_vectish_impl : std::false_type {};
|
|
|
|
template <typename T>
|
|
struct is_vectish_impl<T,
|
|
std::void_t<typename T::value_type, decltype(std::declval<T&>()[std::declval<const typename T::value_type&>()])>>
|
|
: std::true_type {};
|
|
|
|
template <typename T, typename U = void>
|
|
struct is_pairish_impl : std::false_type {};
|
|
|
|
template <typename T>
|
|
struct is_pairish_impl<T,
|
|
std::void_t<typename T::first_type, decltype(std::declval<T&>()[std::declval<const typename T::first_type&>()])>>
|
|
: std::true_type {};
|
|
|
|
template <typename T>
|
|
using is_general_t = std::integral_constant<bool,
|
|
(std::is_same_v<T, std::string> || (!std::is_same_v<T, char> && !std::is_same_v<T, unsigned char> && !std::is_arithmetic_v<T> &&
|
|
!is_pairish_impl<T>::value && !is_mappish_impl<T>::value && !is_vectish_impl<T>::value))>;
|
|
|
|
template <typename T>
|
|
using is_primitive =
|
|
std::integral_constant<bool, std::is_same_v<T, char> || std::is_same_v<T, unsigned char> || std::is_arithmetic_v<T>>;
|
|
|
|
} // namespace details
|
|
|
|
} // namespace sp
|