resultbase.h File Reference

Classes

struct  ResultOkError
 
struct  TmpErrType< T >
 
struct  TmpErrType< ResultOk< T > >
 
class  ResultOk< T >
 
class  ResultOk< T & >
 
class  ResultOk< void >
 
class  ResultMemT< T >
 
struct  ForwardResultPtr< T >
 
class  ResultRef< T >
 
class  ResultBase< T >
 
class  ResultBase< T & >
 
class  ResultBase< void >
 
class  PrivateIsErrorClassHelper< T, IS_OBJECT_REF >
 
class  PrivateIsErrorClassHelper< T, true >
 
class  IsErrorClass< T >
 
class  IsErrorClass< ForwardRef< T > >
 
class  ResultSuper< RESULT_TYPE, ENABLE >
 
class  ResultSuper< RESULT_TYPE, typename SFINAEHelper< void, typename RESULT_TYPE::template ResultFunctions< ResultBase< RESULT_TYPE > > >::type >
 
class  ResultSuper< RESULT_TYPE &, typename SFINAEHelper< void, typename RESULT_TYPE::template ResultFunctions< ResultBase< RESULT_TYPE & > > >::type >
 
class  Result< RESULT_TYPE >
 
struct  RemoveResult< T >
 
struct  RemoveResult< Result< T > >
 
struct  RemoveResult< ResultOk< T > >
 
struct  GenericCastMemberTrait< Result< TO >, Result< FROM >, SAFE >
 
struct  GenericCastTrait< Result< TO >, FROM, SAFE >
 
struct  GenericCastTrait< Result< TO >, Result< FROM >, SAFE >
 
class  ResultIteratorFunctions< SUPER >
 
class  ResultIteratorFunctions< SUPER >::Wrapper
 

Namespaces

 maxon
 
 maxon::details
 

Macros

#define PRIVATE_MAXON_RBF_SENTINEL(...)
 
#define PRIVATE_MAXON_ENABLE_IF_ERROR(TYPE)
 
#define PRIVATE_MAXON_ENABLE_IF_ERROR_DUMMY
 
#define PRIVATE_MAXON_iferr_scope(T)
 
#define PRIVATE_MAXON_iferr_scope_handler()
 
#define PRIVATE_MAXON_iferr_return()
 
#define PRIVATE_MAXON_iferr_cannot_fail(str)
 
#define PRIVATE_MAXON_iferr_ignore_method(str, optionalArg, method, ...)
 
#define PRIVATE_MAXON_iferr_ignore(...)
 
#define iferr_scope
 
#define iferr_scope_handler
 
#define iferr_cannot_fail(str)
 
#define iferr_ignore(...)
 
#define iferr_scope_result
 
#define iferr_return
 
#define iferr_throw(ERR)
 

Typedefs

template<typename T >
using ResultPtr = ResultMemT< T * >
 

Enumerations

enum class  ERROR_OK { VALUE }
 
enum class  ERROR_FAILED { VALUE }
 
enum class  ERROR_TYPE {
  OUT_OF_MEMORY ,
  NULLPTR ,
  ILLEGAL_ARGUMENT ,
  ILLEGAL_STATE ,
  NOT_IMPLEMENTED ,
  UNRESOLVED ,
  UNKNOWN
}
 

Functions

enum maxon::ERROR_OK MAXON_ENUM_LIST (ERROR_OK)
 
enum maxon::ERROR_FAILED MAXON_ENUM_LIST (ERROR_FAILED)
 
enum maxon::ERROR_TYPE MAXON_ENUM_LIST (ERROR_TYPE)
 
const Error * CreateErrorPtr (MAXON_SOURCE_LOCATION_DECLARATION, ERROR_TYPE type) __attribute__((pure
 
ThreadReferencedError CreateError (MAXON_SOURCE_LOCATION_DECLARATION, ERROR_TYPE type)
 
const Error * PrivateSystemSetCurrentError (const Error &error)
 
const Error * PrivateSystemSetCurrentError (Error &&error)
 
void PrivateSetError (Error &dest, const Error *src)
 
 MAXON_MEMBERTYPE_DETECTOR (IsForwardRef, IsForwardRef, std::false_type)
 
template<typename T >
MAXON_ATTRIBUTE_FORCE_INLINE auto operator% (const ResultOk< T > &rv, ThreadReferencedError &err) -> decltype(rv.GetValue())
 
template<typename T >
MAXON_ATTRIBUTE_FORCE_INLINEoperator% (ResultOk< T > &&rv, ThreadReferencedError &err)
 
template<typename T >
MAXON_ATTRIBUTE_FORCE_INLINE T & operator% (ResultOk< T & > &&rv, ThreadReferencedError &err)
 
MAXON_ATTRIBUTE_FORCE_INLINE void operator% (ResultOk< void > &&rv, ThreadReferencedError &err)
 
template<typename T >
MAXON_ATTRIBUTE_FORCE_INLINE auto operator% (const ResultOk< T > &rv, maxon::details::ResultOkError &err) -> decltype(rv.GetValue())
 
template<typename T >
MAXON_ATTRIBUTE_FORCE_INLINEoperator% (ResultOk< T > &&rv, maxon::details::ResultOkError &err)
 
template<typename T >
MAXON_ATTRIBUTE_FORCE_INLINE T & operator% (ResultOk< T & > &&rv, maxon::details::ResultOkError &err)
 
MAXON_ATTRIBUTE_FORCE_INLINE void operator% (ResultOk< void > &&rv, maxon::details::ResultOkError &err)
 
template<typename T >
MAXON_ATTRIBUTE_FORCE_INLINE auto operator% (const Result< T > &rv, ThreadReferencedError &err) -> decltype(rv.GetValue())
 
template<typename T >
MAXON_ATTRIBUTE_FORCE_INLINEoperator% (Result< T > &&rv, ThreadReferencedError &err)
 
template<typename T >
MAXON_ATTRIBUTE_FORCE_INLINE T & operator% (const Result< T & > &rv, ThreadReferencedError &err)
 
template<typename T >
MAXON_ATTRIBUTE_FORCE_INLINE T & operator% (Result< T & > &&rv, ThreadReferencedError &err)
 
MAXON_ATTRIBUTE_FORCE_INLINE void operator% (const Result< void > &rv, ThreadReferencedError &err)
 
MAXON_ATTRIBUTE_FORCE_INLINE void operator% (Result< void > &&rv, ThreadReferencedError &err)
 
template<typename T >
MAXON_ATTRIBUTE_FORCE_INLINE T && operator% (ResultMemT< T > &&ptr, ThreadReferencedError &err)
 
template<typename T >
MAXON_ATTRIBUTE_FORCE_INLINE const T & operator% (const ResultMemT< T > &ptr, ThreadReferencedError &err)
 
template<typename T >
MAXON_ATTRIBUTE_FORCE_INLINE T & operator% (ResultRef< T > ptr, ThreadReferencedError &err)
 

Variables

 VALUE
 
static const ERROR_FAILED FAILED
 
 OUT_OF_MEMORY
 
 NULLPTR
 
 ILLEGAL_ARGUMENT
 
 ILLEGAL_STATE
 
 NOT_IMPLEMENTED
 
 UNRESOLVED
 
 UNKNOWN
 
const Error returns_nonnull
 

Macro Definition Documentation

◆ PRIVATE_MAXON_RBF_SENTINEL

#define PRIVATE_MAXON_RBF_SENTINEL (   ...)

◆ PRIVATE_MAXON_ENABLE_IF_ERROR

#define PRIVATE_MAXON_ENABLE_IF_ERROR (   TYPE)

◆ PRIVATE_MAXON_ENABLE_IF_ERROR_DUMMY

#define PRIVATE_MAXON_ENABLE_IF_ERROR_DUMMY

◆ PRIVATE_MAXON_iferr_scope

#define PRIVATE_MAXON_iferr_scope (   T)

◆ PRIVATE_MAXON_iferr_scope_handler

#define PRIVATE_MAXON_iferr_scope_handler ( )

◆ PRIVATE_MAXON_iferr_return

#define PRIVATE_MAXON_iferr_return ( )

◆ PRIVATE_MAXON_iferr_cannot_fail

#define PRIVATE_MAXON_iferr_cannot_fail (   str)

◆ PRIVATE_MAXON_iferr_ignore_method

#define PRIVATE_MAXON_iferr_ignore_method (   str,
  optionalArg,
  method,
  ... 
)

◆ PRIVATE_MAXON_iferr_ignore

#define PRIVATE_MAXON_iferr_ignore (   ...)

◆ iferr_scope

#define iferr_scope

Instead of using iferr you can define an iferr_scope and within this scope call methods which might return an error (and decorate them with the iferr_return attribute). If a method returns with an error iferr_return will forward it.

FuncA() iferr_return;
FuncB() iferr_return;
#define iferr_scope
Definition: resultbase.h:1374
#define iferr_return
Definition: resultbase.h:1465

◆ iferr_scope_handler

#define iferr_scope_handler

To perform a specific action in case of an error (additional logging, or just to set a breakpoint for debugging) you can replace iferr_scope by an iferr_scope_handler:

{
DebugStop("special message");
return err;
};
FuncA() iferr_return;
FuncB() iferr_return;
#define DebugStop(...)
Definition: debugdiagnostics.h:231
#define iferr_scope_handler
Definition: resultbase.h:1392

iferr_scope_handler implicitely defines the error variable 'err'.

◆ iferr_cannot_fail

#define iferr_cannot_fail (   str)

If an error cannot occur (because you've ensured this by preallocating resources or the algorithm was designed in such a way, etc.) you might use iferr_cannot_fail with a comment which explans why it can't fail. In debug this will check for errors and invoke DebugStop() to notify you that your code is broken, but in release there are no error checks.

BaseArray<Int> array;
array.EnsureCapacity(42) iferr_return;
for (Int i = 0; i < GetCapacityCount(); i++)
array.Append(i) iferr_cannot_fail("Capacity was ensured.");
Py_ssize_t i
Definition: abstract.h:645
maxon::Int Int
Definition: ge_sys_math.h:64
#define iferr_cannot_fail(str)
Definition: resultbase.h:1409

◆ iferr_ignore

#define iferr_ignore (   ...)

If for perfomance reasons a piece of code has been very carefully designed in a way that error checking is performed at the very end and that no checks are necessary inbetween you may qualify calls with iferr_ignore and a comment which describes why the error can be ignored.

Note
This should only be used for performance critical code which has been profiled properly and has been reviewed thoroughly.
You might supply an optional second parameter (debug) to cause a DebugStop on error.
BaseArray<Int> array;
const Int CNT = 42;
for (Int i = 0; i < CNT; i++)
array.Append(i) iferr_ignore("Errors are handled after append");
if (array.GetCount() != CNT)
return OutOfMemoryError(MAXON_SOURCE_LOCATION);
#define MAXON_SOURCE_LOCATION
Definition: memoryallocationbase.h:67
#define iferr_ignore(...)
Definition: resultbase.h:1430

◆ iferr_scope_result

#define iferr_scope_result

Use iferr_scope_result in finally blocks to deallocate resources based on the error state.

finally
{
destructSecond = true;
};
FAILED
Generic error if a rendering has failed due to missing license or similar.
Definition: ge_prepass.h:8
#define iferr_scope_result
Definition: resultbase.h:1442

◆ iferr_return

#define iferr_return

The iferr_return macro is the easiest way to introduce error handling. It quickly allows you leave a function as soon as an error occurs. iferr_return requires you to define iferr_scope or iferr_scope_handler once beforehand (preferably at the beginning of your function)

...
for (Int i = 0; i < 5; i++)
{
array.Append(5) iferr_return;
}
MyRef ref = MyRef::Create() iferr_return;
PyObject * obj
Definition: complexobject.h:60
static auto Create(ARGS &&... args)
Definition: apibase.h:2750

iferr_return forwards the error to the calling function. To do this your function must either return Result<T> or use an iferr_scope_handler.
When iferr_return is used within 'for', 'if', 'else' or 'while' those statements must use brackets around their scope, otherwise iferr_return will not be properly executed.

◆ iferr_throw

#define iferr_throw (   ERR)

Manually throw an error. Especially useful in combination with iferr_scope_handler to cleanup things in case of errors. Usually you just create error messages and return them in case of a problem like in this example:

static Result<void> DoSomething()
{
Char* mem = NewMem(Char, 200) iferr_return;
while (true)
{
// do something
...
if (FuncA() != 2)
return IllegalStateError(MAXON_SOURCE_LOCATION, "Invalid return value"_s);
...
if (FuncB() != 40)
return IllegalStateError(MAXON_SOURCE_LOCATION, "Invalid return value"_s);
...
if (FuncC() != -3)
return IllegalStateError(MAXON_SOURCE_LOCATION, "Invalid return value"_s);
}
DeleteMem(mem);
return OK;
}
#define NewMem(T, cnt)
Definition: defaultallocator.h:195
OK
Ok.
Definition: ge_prepass.h:0
maxon::Char Char
Definition: ge_sys_math.h:56
void DeleteMem(T *&p)
Definition: defaultallocator.h:257

The big problem is that in case of an error the allocated chars are nevers freed. Instead of deleting the mem at each possible error point in the algo you can throw the error instead of returning them and then catch the error with iferr_scope_handler and handle the cleanup at a single place like in this example:

static Result<void> DoSomething()
{
Char* mem = nullptr;
{
DeleteMem(mem); // always guarantee cleanup even in error case
return err;
};
mem = NewMem(Char, 200) iferr_return;
while (true)
{
// do something
...
if (FuncA() != 2)
iferr_throw(IllegalStateError(MAXON_SOURCE_LOCATION, "Invalid return value"_s));
...
if (FuncB() != 40)
iferr_throw(IllegalStateError(MAXON_SOURCE_LOCATION, "Invalid return value"_s));
...
if (FuncC() != -3)
iferr_throw(IllegalStateError(MAXON_SOURCE_LOCATION, "Invalid return value"_s));
}
DeleteMem(mem);
return OK;
}
#define iferr_throw(ERR)
Definition: resultbase.h:1528

Variable Documentation

◆ VALUE

VALUE

The single value of this enum.

◆ OUT_OF_MEMORY

OUT_OF_MEMORY

Create an OutOfMemoryError.

◆ NULLPTR

NULLPTR

Create a NullptrError.

◆ ILLEGAL_ARGUMENT

ILLEGAL_ARGUMENT

Create an IllegalArgumentError.

◆ ILLEGAL_STATE

ILLEGAL_STATE

Create an IllegalStateError.

◆ NOT_IMPLEMENTED

NOT_IMPLEMENTED

Create a FunctionNotImplementedError.

◆ UNRESOLVED

UNRESOLVED

Create an UnresolvedError.

◆ UNKNOWN

UNKNOWN

< Create an UnknownError.