239 lines
6.2 KiB
C++
239 lines
6.2 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<typename T, typename U = void>
|
|
struct IsPairImpl : AuFalseType
|
|
{ };
|
|
|
|
template<typename T>
|
|
struct IsPairImpl <T, AuVoid_t<typename T::first_type,
|
|
typename T::second_type,
|
|
decltype(&T::first),
|
|
decltype(&T::second)>> : AuTrueType
|
|
{
|
|
};
|
|
|
|
template <class T, class Enable = void>
|
|
struct AuIsPair_C;
|
|
|
|
template <class T>
|
|
struct AuIsPair_C<T, AuEnableIf_t<IsPairImpl<T>::value>>
|
|
{
|
|
using type = AuPair<typename T::first_type, typename T::second_type>;
|
|
};
|
|
|
|
template <class T>
|
|
struct AuIsPair_C<T, AuEnableIf_t<!IsPairImpl<T>::value>>
|
|
{
|
|
using type = void;
|
|
};
|
|
|
|
template <class T>
|
|
constexpr inline bool AuIsPair_v = AuIsSame_v<typename AuIsPair_C<AuRemoveCV_t<T>>::type, AuRemoveCV_t<T>>;
|
|
|
|
template <class... Args>
|
|
static auto AuMakePair(Args&&... args)
|
|
{
|
|
return AURORA_RUNTIME_MAKE_PAIR(AuForward<Args>(args)...);
|
|
}
|
|
|
|
template<typename T>
|
|
struct AuIsTuple : AuFalseType
|
|
{ };
|
|
|
|
template<typename... Ts>
|
|
struct AuIsTuple<AuTuple<Ts...>> : AuTrueType
|
|
{ };
|
|
|
|
template <class T>
|
|
inline constexpr bool AuIsTuple_v = AuIsTuple<T>::type::value;
|
|
|
|
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 <AuUInt N, typename... Args>
|
|
static auto &AuGet(Args&... args)
|
|
{
|
|
return AURORA_RUNTIME_GET_TUPLE<N>(AuForward<Args &>(args)...);
|
|
}
|
|
|
|
template <AuUInt N, typename... Args>
|
|
static const auto &AuGet(const Args&... args)
|
|
{
|
|
return AURORA_RUNTIME_GET_TUPLE<N>(AuForward<const Args &>(args)...);
|
|
}
|
|
|
|
template <AuUInt N, typename... Args>
|
|
static const auto &&AuGet(const Args&&... args)
|
|
{
|
|
return AURORA_RUNTIME_GET_TUPLE<N>(AuForward<const 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);
|
|
}
|
|
|
|
template <class T>
|
|
inline constexpr AuUInt AuTupleCountOf_v = AURORA_RUNTIME_TUPLE_SIZE<AuRemoveConst_t<AuRemoveReference_t<T>>>::value;
|
|
|
|
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<1>(tuple, AuMakeIndexSequence<AuTupleCountOf_v<decltype(tuple)> -1>());
|
|
}
|
|
|
|
template <class... Ts>
|
|
static auto AuTuplePopBack(const AuTuple<Ts...> &tuple)
|
|
{
|
|
return __audetail::AuTuplePopImpl<0>(tuple, AuMakeIndexSequence<AuTupleCountOf_v<decltype(tuple)> - 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>());
|
|
}
|
|
|
|
template <class Tuple, class Invokable>
|
|
static void AuTupleForEach(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, class 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, class... Ts>
|
|
static auto AuTupleTransform(const AuTuple<Ts...> &tuple, const Invokable &translate)
|
|
{
|
|
return __audetail::AuTupleTransformImpl(translate,
|
|
tuple,
|
|
AuMakeIndexSequence<sizeof...(Ts)>());
|
|
} |