/*** 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 struct IsPairImpl : AuFalseType { }; template struct IsPairImpl > : AuTrueType { }; template struct AuIsPair_C; template struct AuIsPair_C::value>> { using type = AuPair; }; template struct AuIsPair_C::value>> { using type = void; }; template constexpr bool AuIsPair_v = AuIsSame_v>::type, AuRemoveCV_t>; template static auto AuMakePair(Args&&... args) { return AURORA_RUNTIME_MAKE_PAIR(AuForward(args)...); } template struct AuIsTuple : AuFalseType { }; template struct AuIsTuple> : AuTrueType { }; template constexpr bool AuIsTuple_v = AuIsTuple::type::value; template static auto AuMakeTuple(Args&&... args) { return AURORA_RUNTIME_MAKE_TUPLE(AuForward(args)...); } template static auto &&AuGet(Args&&... args) { return AURORA_RUNTIME_GET_TUPLE(AuForward(args)...); } template static auto &AuGet(Args&... args) { return AURORA_RUNTIME_GET_TUPLE(AuForward(args)...); } template static const auto &AuGet(const Args&... args) { return AURORA_RUNTIME_GET_TUPLE(AuForward(args)...); } template static const auto &&AuGet(const Args&&... args) { return AURORA_RUNTIME_GET_TUPLE(AuForward(args)...); } template static auto AuTupleCat(Args&&... args) { return AURORA_RUNTIME_TUPLE_CAT(AuForward(args)...); } template static auto AuTupleApply(F &&f, Tuple &&t) { return AURORA_RUNTIME_APPLY(f, t); } template constexpr AuUInt AuTupleCountOf_v = AURORA_RUNTIME_TUPLE_SIZE>>::value; namespace __audetail { template static auto AuTuplePopImpl(const Tuple &tuple, AuIndexSequence) { return AURORA_RUNTIME_MAKE_TUPLE(AuGet(tuple)...); } } template static auto AuTuplePopFront(const AuTuple &tuple) { return __audetail::AuTuplePopImpl<1>(tuple, AuMakeIndexSequence -1>()); } template static auto AuTuplePopBack(const AuTuple &tuple) { return __audetail::AuTuplePopImpl<0>(tuple, AuMakeIndexSequence - 1>()); } template static auto AuTuplePushFront(const AuTuple &tuple, const T &t) { return AURORA_RUNTIME_TUPLE_CAT(AURORA_RUNTIME_MAKE_TUPLE(t), tuple); } template static auto AuTuplePushFront(const AuTuple &tuple, T &&t) { return AURORA_RUNTIME_TUPLE_CAT(AURORA_RUNTIME_MAKE_TUPLE(t), tuple); } template static auto AuTuplePushBack(const AuTuple &tuple, const T &t) { return AURORA_RUNTIME_TUPLE_CAT(tuple, AURORA_RUNTIME_MAKE_TUPLE(t)); } template static auto AuTuplePushBack(const AuTuple &tuple, T &&t) { return AURORA_RUNTIME_TUPLE_CAT(tuple, AURORA_RUNTIME_MAKE_TUPLE(t)); } template static auto AuTupleTakeRange(const AuTuple &tuple) { return __audetail::AuTuplePopImpl(tuple, AuMakeIndexSequence()); } template static void AuTupleForEach(Tuple &tuple, const Invokable &callback) { AURORA_RUNTIME_APPLY([callback](auto& ...x) { (..., callback(x)); }, tuple); } template static constexpr AuTuple AuTupleTie(Args& ... args) { return AuTuple(args...); } template static constexpr AuTuple AuTupleForward(Args&& ... args) { return AuTuple(AuForward(args)...); } // Stolen: https://codereview.stackexchange.com/questions/193420/apply-a-function-to-each-element-of-a-tuple-map-a-tuple namespace __audetail { template static auto AuTupleTransformImpl(const Fn &fn, Argument &&argument, AuIndexSequence) { if constexpr (sizeof...(Ns) == 0) { return AuTuple<>(); } else if constexpr (AuIsSame_v(argument))), void>) { (fn(AuGet(argument)), ...); return; } else if constexpr (AuIsLValueReference_v(argument)))>) { return AuTupleTie(fn(AuGet(argument))...); } else if constexpr (AuIsRValueReference_v(argument)))>) { return AuTupleForward(fn(AuGet(argument))...); } else { return AuTuple(fn(AuGet(argument))...); } } } template static auto AuTupleTransform(const AuTuple &tuple, const Invokable &translate) { return __audetail::AuTupleTransformImpl(translate, tuple, AuMakeIndexSequence()); }