[+] AuTryCall
[+] AuTryCallPair [+] AuIsCallable [+] AuIsCallable_v [*] Improved AuResetMember
This commit is contained in:
parent
3200e9cb46
commit
dba4a884ca
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
38
Include/auROXTL/auTryCall.hpp
Normal file
38
Include/auROXTL/auTryCall.hpp
Normal 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 }; }
|
||||
};
|
76
Include/auROXTL/auTryCallUtils.hpp
Normal file
76
Include/auROXTL/auTryCallUtils.hpp
Normal 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
|
@ -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>
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user