AuroraRuntime/Include/auROXTL/auTupleUtils.hpp

176 lines
4.7 KiB
C++

/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: auTupleUtils.hpp
Date: 2022-2-1
File: AuroraUtils.hpp
File: auROXTLUtils.hpp
Date: 2021-6-9
Author: Reece
***/
#pragma once
#include "auIntegerSequence.hpp"
#if !defined(AURORA_RUNTIME_MAKE_PAIR)
#define AURORA_RUNTIME_MAKE_PAIR std::make_pair
#endif
#if !defined(AURORA_RUNTIME_MAKE_TUPLE)
#define AURORA_RUNTIME_MAKE_TUPLE std::make_tuple
#endif
#if !defined(AURORA_RUNTIME_GET_TUPLE)
#define AURORA_RUNTIME_GET_TUPLE std::get
#endif
#if !defined(AURORA_RUNTIME_TUPLE_CAT)
#define AURORA_RUNTIME_TUPLE_CAT std::tuple_cat
#endif
#if !defined(AURORA_RUNTIME_TUPLE_SIZE)
#define AURORA_RUNTIME_TUPLE_SIZE std::tuple_size
#endif
#if !defined(AURORA_RUNTIME_APPLY)
#define AURORA_RUNTIME_APPLY std::apply
#endif
template <class... Args>
static auto AuMakePair(Args&&... args)
{
return AURORA_RUNTIME_MAKE_PAIR(AuForward<Args>(args)...);
}
template <class... Args>
static auto AuMakeTuple(Args&&... args)
{
return AURORA_RUNTIME_MAKE_TUPLE(AuForward<Args>(args)...);
}
template <AuUInt N, typename... Args>
static auto &AuGet(Args&&... args)
{
return AURORA_RUNTIME_GET_TUPLE<N>(AuForward<Args>(args)...);
}
template <class... Args>
static auto AuTupleCat(Args&&... args)
{
return AURORA_RUNTIME_TUPLE_CAT(AuForward<Args>(args)...);
}
template <class F, class Tuple>
static auto AuTupleApply(F &&f, Tuple &&t)
{
return AURORA_RUNTIME_APPLY(f, t);
}
namespace __audetail
{
template <AuUInt Offset, class Tuple, AuUInt... Is>
static auto AuTuplePopImpl(const Tuple &tuple, AuIndexSequence<Is...>)
{
return AURORA_RUNTIME_MAKE_TUPLE(AuGet<Is + Offset>(tuple)...);
}
}
template <class... Ts>
static auto AuTuplePopFront(const AuTuple<Ts...> &tuple)
{
return __audetail::AuTuplePopImpl<0>(tuple, AuMakeIndexSequence<AURORA_RUNTIME_TUPLE_SIZE<tuple>::value - 1>());
}
template <class... Ts>
static auto AuTuplePopBack(const AuTuple<Ts...> &tuple)
{
return __audetail::AuTuplePopImpl<1>(tuple, AuMakeIndexSequence<AURORA_RUNTIME_TUPLE_SIZE<tuple>::value - 1>());
}
template <class T, class... Ts>
static auto AuTuplePushFront(const AuTuple<Ts...> &tuple, const T &t)
{
return AURORA_RUNTIME_TUPLE_CAT(AURORA_RUNTIME_MAKE_TUPLE(t), tuple);
}
template <class T, class... Ts>
static auto AuTuplePushFront(const AuTuple<Ts...> &tuple, T &&t)
{
return AURORA_RUNTIME_TUPLE_CAT(AURORA_RUNTIME_MAKE_TUPLE(t), tuple);
}
template <class T, class... Ts>
static auto AuTuplePushBack(const AuTuple<Ts...> &tuple, const T &t)
{
return AURORA_RUNTIME_TUPLE_CAT(tuple, AURORA_RUNTIME_MAKE_TUPLE(t));
}
template <class T, class... Ts>
static auto AuTuplePushBack(const AuTuple<Ts...> &tuple, T &&t)
{
return AURORA_RUNTIME_TUPLE_CAT(tuple, AURORA_RUNTIME_MAKE_TUPLE(t));
}
template <AuUInt Start, AuUInt Length, class... Ts>
static auto AuTupleTakeRange(const AuTuple<Ts...> &tuple)
{
return __audetail::AuTuplePopImpl<Start>(tuple, AuMakeIndexSequence<Length - 1>());
}
template <class Tuple, class Invokable>
static void AuTupleForEach(const Tuple &tuple, const Invokable &callback)
{
AURORA_RUNTIME_APPLY([callback](auto& ...x)
{
(..., callback(x));
}, tuple);
}
template <class ... Args>
static constexpr AuTuple<Args& ...> AuTupleTie(Args& ... args)
{
return AuTuple<Args&...>(args...);
}
template <class ... Args>
static constexpr AuTuple<Args&& ...> AuTupleForward(Args&& ... args)
{
return AuTuple<Args&&...>(AuForward<Args>(args)...);
}
// Stolen: https://codereview.stackexchange.com/questions/193420/apply-a-function-to-each-element-of-a-tuple-map-a-tuple
namespace __audetail
{
template <class Fn, typename Argument, AuUInt... Ns>
static auto AuTupleTransformImpl(const Fn &fn, Argument &&argument, AuIndexSequence<Ns...>)
{
if constexpr (sizeof...(Ns) == 0)
{
return AuTuple<>();
}
else if constexpr (AuIsSame_v<decltype(fn(AuGet<0>(argument))), void>)
{
(fn(AuGet<Ns>(argument)), ...);
return;
}
else if constexpr (AuIsLValueReference_v<decltype(fn(AuGet<0>(argument)))>)
{
return AuTupleTie(fn(AuGet<Ns>(argument))...);
}
else if constexpr (AuIsRValueReference_v<decltype(fn(AuGet<0>(argument)))>)
{
return AuTupleForward(fn(AuGet<Ns>(argument))...);
}
else
{
return AuTuple(fn(AuGet<Ns>(argument))...);
}
}
}
template <class Invokable, typename... Ts>
static auto AuTupleTransform(const AuTuple<Ts...> &tuple, const Invokable &translate)
{
return __audetail::AuTupleTransformImpl(translate, tuple,
AuMakeIndexSequence<sizeof...(Ts)>());
}