[+] AuTryCall
[+] AuTryCallPair [+] AuIsCallable [+] AuIsCallable_v [*] Improved AuResetMember
This commit is contained in:
parent
3200e9cb46
commit
dba4a884ca
@ -7,10 +7,19 @@
|
|||||||
***/
|
***/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
template <class T>
|
template <class T, class ...Args>
|
||||||
static void AuResetMember(T &ref)
|
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>
|
template <class T>
|
||||||
|
@ -25,16 +25,7 @@ struct AuResult
|
|||||||
AuResult(T &&value) : type(value), success(true)
|
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,
|
// Forced return value optimization.
|
||||||
// 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()
|
|
||||||
|
|
||||||
T &GetResult()
|
T &GetResult()
|
||||||
{
|
{
|
||||||
return type;
|
return type;
|
||||||
|
@ -68,6 +68,10 @@ namespace _audetail
|
|||||||
|
|
||||||
template <class B, typename D>
|
template <class B, typename D>
|
||||||
auto TestIsBaseOf(int) -> decltype(TestIsPtrConvertible<B>(static_cast<D *>(nullptr)));
|
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>
|
template <class T>
|
||||||
@ -253,7 +257,7 @@ template <class T>
|
|||||||
using AuAddRReference_t = typename AuAddRReference<T>::type;
|
using AuAddRReference_t = typename AuAddRReference<T>::type;
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
AuAddRReference_t<T> AuDeclVal();
|
T &&AuDeclVal();
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct AuAddConst
|
struct AuAddConst
|
||||||
@ -353,4 +357,24 @@ template <template <class...> class Base, typename Derived>
|
|||||||
using AuIsBaseOfTemplate = typename AuIsBaseOfTemplateImpl<Base, Derived>::type;
|
using AuIsBaseOfTemplate = typename AuIsBaseOfTemplateImpl<Base, Derived>::type;
|
||||||
|
|
||||||
template <template <class...> class Base, typename Derived>
|
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/auTypes.hpp>
|
||||||
#include <auROXTL/auTryConstruct.hpp>
|
#include <auROXTL/auTryConstruct.hpp>
|
||||||
|
#include <auROXTL/auTryCall.hpp>
|
||||||
#include <auROXTL/auTemplateMeta.hpp>
|
#include <auROXTL/auTemplateMeta.hpp>
|
||||||
#include <auROXTL/auResult.hpp>
|
#include <auROXTL/auResult.hpp>
|
||||||
#include <auROXTL/auMemoryModel.hpp>
|
#include <auROXTL/auMemoryModel.hpp>
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include <auROXTL/auFNV1Utils.hpp>
|
#include <auROXTL/auFNV1Utils.hpp>
|
||||||
#include <auROXTL/auHashUtils.hpp>
|
#include <auROXTL/auHashUtils.hpp>
|
||||||
#include <auROXTL/auTryConstructUtils.hpp>
|
#include <auROXTL/auTryConstructUtils.hpp>
|
||||||
|
#include <auROXTL/auTryCallUtils.hpp>
|
||||||
|
|
||||||
#include <auROXTL/Objects/SafeDestroy.hpp>
|
#include <auROXTL/Objects/SafeDestroy.hpp>
|
||||||
#include <auROXTL/Objects/ResetMember.hpp>
|
#include <auROXTL/Objects/ResetMember.hpp>
|
||||||
|
Loading…
Reference in New Issue
Block a user