[+] AuTryCall

[+] AuTryCallPair
[+] AuIsCallable
[+] AuIsCallable_v
[*] Improved AuResetMember
This commit is contained in:
Reece Wilson 2022-11-17 02:28:23 +00:00
parent 3200e9cb46
commit dba4a884ca
7 changed files with 155 additions and 15 deletions

View File

@ -7,10 +7,19 @@
***/
#pragma once
template <class T>
static void AuResetMember(T &ref)
template <class T, class ...Args>
static void AuResetMember(T &ref, Args &&...args)
{
ref = AuDecay_t<T>();
if constexpr (AuIsClass_v<T>)
{
ref.~T();
AuMemset(&ref, 0, sizeof(ref));
new (&ref) T(AuForward<Args &&>(args)...);
}
else
{
ref = AuDecay_t<T>();
}
}
template <class T>

View File

@ -25,16 +25,7 @@ struct AuResult
AuResult(T &&value) : type(value), success(true)
{}
// I could be pulling this out of my ass, but i'd assume with callee provided stack space being provided through arg0 in most abis,
// and with the callers binary originating from a file in which contains the T declaration, i'd assume it would be faster to chuck
// the return value in the callers' stack **and** access it by reference in the callee, rather than assigning a value using move
// constructors/assignment operators whenever the data is available.
// Feels like a landmine of accidental allocates:
// ...what is the default constructor doing in the caller? (hopefully nothing)
// ...does the object even support move semantics? (would AuResult<T>(AuMove(t)) result in a copy no matter what?)
//
// generally recommend ::GetResult()
// Forced return value optimization.
T &GetResult()
{
return type;

View File

@ -68,6 +68,10 @@ namespace _audetail
template <class B, typename D>
auto TestIsBaseOf(int) -> decltype(TestIsPtrConvertible<B>(static_cast<D *>(nullptr)));
// yoinked: https://stackoverflow.com/a/40867906
template<typename Func, typename...Params> static auto IsCallable(int) -> decltype((void)AuDeclVal<Func>()(AuDeclVal<Params>()...), AuTrueType {});
template<typename Func, typename...Params> static AuFalseType IsCallable(...);
}
template <class T>
@ -253,7 +257,7 @@ template <class T>
using AuAddRReference_t = typename AuAddRReference<T>::type;
template <class T>
AuAddRReference_t<T> AuDeclVal();
T &&AuDeclVal();
template <class T>
struct AuAddConst
@ -353,4 +357,24 @@ template <template <class...> class Base, typename Derived>
using AuIsBaseOfTemplate = typename AuIsBaseOfTemplateImpl<Base, Derived>::type;
template <template <class...> class Base, typename Derived>
inline constexpr bool AuIsBaseOfTemplate_v = AuIsBaseOfTemplateImpl<Base, Derived>::type::value;
inline constexpr bool AuIsBaseOfTemplate_v = AuIsBaseOfTemplateImpl<Base, Derived>::type::value;
// :(
// we have a boost licensed call traits in auv8pp
#include <type_traits>
#if defined(AU_LANG_CPP_14)
template <class T, class... Args>
using AuResultOf_t = typename std::result_of_t<T, Args...>;
#else
template <class T, class... Args>
using AuResultOf_t = typename std::invoke_result_t<T, Args...>;
#endif
template <class Func, class ...Params>
struct AuCallable : decltype(_audetail::IsCallable<Func, Params...>(0))
{
};
template <class F, class... Args>
constexpr auto AuIsCallable_v = AuCallable<F, Args...>::value;

View File

@ -0,0 +1,38 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: auTryCall.hpp
Date: 2022-11-16
Author: Reece
***/
#pragma once
struct AuCallErrorTag
{
/*
Thy shall fulfill the following requirements:
operator bool() const;
static constexpr AuCallErrorTag Failed ();
static constexpr AuCallErrorTag Success();
*/
};
struct AuErrorCode_t : AuCallErrorTag
{
AuUInt32 uValue;
inline constexpr AuErrorCode_t()
{};
inline constexpr AuErrorCode_t(AuUInt32 uValue) : uValue(uValue)
{};
explicit inline operator bool() const
{
return bool(uValue == 0);
}
static constexpr AuErrorCode_t Failed () { return AuErrorCode_t { AuUInt32(1) << 31 }; }
static constexpr AuErrorCode_t Catch () { return AuErrorCode_t { (AuUInt32(1) << 31) | 1 }; }
static constexpr AuErrorCode_t Success() { return AuErrorCode_t { 0 }; }
};

View File

@ -0,0 +1,76 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: auTryCallUtils.hpp
Date: 2022-11-16
Author: Reece
***/
#pragma once
#define _AU_TRYCALL_CHECKCODE(X) AU_TEMPLATE_ENABLE_WHEN(AuIsBaseOf_v<AuCallErrorTag, CtorCode_t> && !AuIsSame_v<X, CtorCode_t>)
template <class CtorCode_t = AuErrorCode_t, class Callable_t, typename ... Args, _AU_TRYCALL_CHECKCODE(Callable_t)>
inline auto AuTryCall(Callable_t callable, CtorCode_t &status, Args&& ... args)
{
if constexpr (AuIsCallable_v<Callable_t, Args&& ..., CtorCode_t &>)
{
status = CtorCode_t::Failed();
return callable(AuForward<Args&&>(args)..., AuReference(status));
}
else
{
static_assert(AuIsCallable_v<Callable_t, Args&& ...>, "bad try-call prototype");
try
{
status = CtorCode_t::Success();
return callable(AuForward<Args &&>(args)...);
}
catch (...)
{
status = CtorCode_t::Failed();
return AuResultOf_t<Callable_t, Args...>();
}
}
}
template <class CtorCode_t = AuErrorCode_t, class Callable_t, typename ... Args, class T, _AU_TRYCALL_CHECKCODE(T)>
inline CtorCode_t AuTryCall(Callable_t callable, T &ref, Args&& ... args)
{
CtorCode_t status;
if constexpr (AuIsCallable_v<Callable_t, Args ..., CtorCode_t &>)
{
ref = callable(AuForward<Args>(args)..., AuReference(status));
return status;
}
else
{
try
{
ref = callable(AuForward<Args>(args)...);
return CtorCode_t::Success();
}
catch (...)
{
ref = AuMove(T());
if constexpr (AuIsSame_v<CtorCode_t, AuErrorCode_t>)
{
return CtorCode_t::Catch();
}
else
{
return CtorCode_t::Failed();
}
}
}
}
template <class CtorCode_t = AuErrorCode_t, class Callable_t, typename ... Args, _AU_TRYCALL_CHECKCODE(Callable_t)>
inline auto AuTryCallPair(Callable_t callable, Args&& ... args)
{
CtorCode_t code;
auto a = AuTryCall<CtorCode_t, Callable_t, Args...>(callable, AuReference(code), AuForward<Args &&>(args)...);
return AuMakePair(AuMove(code), a);
}
#undef _AU_TRYCALL_CHECKCODE

View File

@ -27,6 +27,7 @@
#include <auROXTL/auTypes.hpp>
#include <auROXTL/auTryConstruct.hpp>
#include <auROXTL/auTryCall.hpp>
#include <auROXTL/auTemplateMeta.hpp>
#include <auROXTL/auResult.hpp>
#include <auROXTL/auMemoryModel.hpp>

View File

@ -48,6 +48,7 @@
#include <auROXTL/auFNV1Utils.hpp>
#include <auROXTL/auHashUtils.hpp>
#include <auROXTL/auTryConstructUtils.hpp>
#include <auROXTL/auTryCallUtils.hpp>
#include <auROXTL/Objects/SafeDestroy.hpp>
#include <auROXTL/Objects/ResetMember.hpp>