Files
mijin2/source/mijin/util/misc.hpp

70 lines
1.7 KiB
C++

#pragma once
#if !defined(MIJIN_UTIL_MISC_HPP_INCLUDED)
#define MIJIN_UTIL_MISC_HPP_INCLUDED 1
#include <array>
#include <tuple>
#include <utility>
#include "./traits.hpp"
namespace mijin
{
//
// public functions
//
template<auto V, typename T>
constexpr decltype(auto) idValue(T&& value)
{
return std::forward<T>(value);
}
namespace impl
{
template<typename T, typename... TArgs>
struct ConstructArrayHelper
{
template<std::size_t... I>
static constexpr std::array<T, sizeof...(I)> construct(const TArgs&... args, std::index_sequence<I...>)
{
return {idValue<I>(T(args...))...};
}
};
}
template<typename T, std::size_t count, typename... TArgs>
constexpr std::array<T, count> constructArray(const TArgs&... args)
{
return impl::ConstructArrayHelper<T, TArgs...>::construct(args..., std::make_index_sequence<count>());
}
template<typename TFunction, typename... TArgs>
constexpr auto applyPack(TFunction&& function, TArgs&&... args)
{
auto doApply = [&]<std::size_t... Idx>(std::index_sequence<Idx...>)
{
if constexpr (!is_any_type_v<void, std::invoke_result_t<TFunction, std::size_t, TArgs>...>) {
return std::make_tuple(std::invoke(function, Idx, args) ...);
}
else {
(std::invoke(function, Idx, args), ...);
}
};
return doApply(std::index_sequence_for<TArgs...>());
}
template<typename TFunction, typename TTuple>
constexpr auto applyWithIndex(TFunction&& function, TTuple&& tuple)
{
auto doApply = [&]<typename... TArgs>(TArgs&&... args)
{
return applyPack(std::forward<TFunction>(function), std::forward<TArgs>(args)...);
};
return std::apply(doApply, std::forward<TTuple>(tuple));
}
}
#endif // !defined(MIJIN_UTIL_MISC_HPP_INCLUDED)