-
Notifications
You must be signed in to change notification settings - Fork 0
Exceptions
The Default exception type only needs a predicate and will throw on failure.
The predicate will automatically be logged as a string in the message.
SA_ASSERT((Default, MyInit()), MyChannel, "MyAPI initialization failed");
[17:3:11][0] {AssertFailure - MyChannel} main.cpp:37 - int main()
Msg: MyInit() evaluated to false!
Dets: MyAPI initialization failed
See unit tests for more examples.
The Equals exception is used to ensure equality (throw on failure aka NOT equals).
LHS and RHS arguments must be provided. Their names and values will automatically be logged as a string.
SA_ASSERT((Equals, myInt1, myInt2), MyChannel, "My details");
[17:4:4][0] {AssertFailure - MyChannel} main.cpp:38 - int main()
Msg: 'myInt1' == 'myInt2' => { 1 == 2 }: Values must be equal.
Dets: My details
For float and double parameters, a 'NearlyEquals' is performed using std::numeric_limits<T>::epsilon()
.
See unit tests for more examples.
Specialization for friendly equals 0 checks.
SA_ASSERT((Equals0, myInt1), MyChannel, "My details");
[17:8:41][0] {AssertFailure - MyChannel} main.cpp:43 - int main()
Msg: myInt1 == i() => { 1 == 0 }: Values must be equal.
Dets: My details
See unit tests for more examples.
Specialization for friendly equals 1 checks.
SA_ASSERT((Equals1, myInt1), MyChannel, "My details");
[17:9:36][0] {AssertSuccess - MyChannel} main.cpp:43 - int main()
Msg: myInt1 == i(1) => { 1 == 1 }: Values must be equal.
Dets: My details
See unit tests for more examples.
The NotEquals exception is used to ensure non-equality (throw on failure aka EQUALS).
LHS and RHS arguments must be provided. Their names and values will automatically be logged as a string.
SA_ASSERT((NotEquals, myInt1, myInt2), MyChannel, "My details");
[17:4:4][0] {AssertSuccess - MyChannel} main.cpp:38 - int main()
Msg: 'myInt1' != 'myInt2' => { 1 != 2 }: Values must be NOT equal.
Dets: My details
For float and double parameters, a 'NearlyEquals' is performed using std::numeric_limits<T>::epsilon()
.
See unit tests for more examples.
Specialization for friendly not equals 0 checks.
SA_ASSERT((NotEquals0, myInt1), MyChannel, "My details");
[17:8:41][0] {AssertSuccess - MyChannel} main.cpp:43 - int main()
Msg: myInt1 != i() => { 1 != 0 }: Values must be NOT equal.
Dets: My details
See unit tests for more examples.
Specialization for friendly not equals 1 checks.
SA_ASSERT((NotEquals1, myInt1), MyChannel, "My details");
[17:9:36][0] {AssertFailure - MyChannel} main.cpp:43 - int main()
Msg: myInt1 != i(1) => { 1 != 1 }: Values must be NOT equal.
Dets: My details
See unit tests for more examples.
The Nullptr exception is used to check the NON-nullity of a pointer. Throw on null pointer provided.
SA_ASSERT((Nullptr, myPtr), MyChannel, "My details");
[17:18:5][0] {AssertFailure - MyChannel} main.cpp:48 - int main()
Msg: myPtr must be not null!
Dets: My details
See unit tests for more examples.
The OutOfRange exception is used to check index access range.
currIndex
(index to access), minBound
, and maxBound
arguments must be provided. Their names and values will automatically be logged.
SA_ASSERT((OutOfRange, myIndex, minBound, maxBound), MyChannel, "My details");
[17:22:25][0] {AssertFailure - MyChannel} main.cpp:53 - int main()
Msg: Index 'myIndex' [9] is out of range ['minBound';'maxBound'] => [1;7]
Dets: My details
See unit tests for more examples.
The OutOfArrayRange exception is used to check index access range within an array.
Any array type can be provided, however the size()
method must be implemented.
currIndex
(index to access) and array
must be provided. Additional minBound
and maxBound
within the array size can be provided. All their names and values will automatically be logged.
int myIndex = 1;
std::vector<int> myVector = {1, 5, 3, 8, 6, 2};
SA_ASSERT((OutOfArrayRange, myIndex, myVector), MyChannel, "My details");
SA_ASSERT((OutOfArrayRange, myIndex, myVector, 2, 4), MyChannel, "My details");
[17:27:25][0] {AssertSuccess - MyChannel} main.cpp:58 - int main()
Msg: Index 'myIndex' [1] must be in array 'myVector' range [0;5]
Dets: My details
[17:27:25][0] {AssertFailure - MyChannel} main.cpp:59 - int main()
Msg: Index 'myIndex' [1] must be in array 'myVector' range [2;4]
Dets: My details
terminate called after throwing an instance of 'SA::Exception_OutOfArrayRange'
See unit tests for more examples.
The exception system can easily be extended by creating a custom exception type and providing a construction-helper macro.
First, start by defining the new exception class.
#include <SA/Logger/Exceptions/Exception.hpp>
namespace MyNamespace
{
// Custom Exception class.
class MyException : public SA::Exception
{
public:
int i = 0;
float f = 0.0f;
MyException(
BaseInfo _info, // Required info for Exception system.
int _i, // 'i' Value
std::wstring _iStr, // Input 'i' variable name.
float _f, // 'f' Value
std::wstring _fStr, // Input 'f' variable name.
) noexcept :
Exception(
std::move(_info),
_i >= 2 * _f, // Predicate
SA::StringFormat(L"\'%1\' >= 2 * \'%2\' => { %3 >= 2 * %4 }: evaluated to false!", _iStr, _fStr, _i, _f), // Message
),
// Save input parameters' value.
i{ _i },
f{ _f }
{
}
};
} // MyNamespace
Then, below the class definition, add the constructor-helper macro definition with the name __SA_CREATE_EXCEPTION_<exception_type_name>
.
This allow the addition of preprocessed arguments for the exception construction (such as variable names).
/// Define constructor-helper macro.
#define __SA_CREATE_EXCEPTION_MyException(_baseInfo, _i, _f) MyNamespace::MyException(\
_baseInfo,\
_i,\
SA_WSTR(_i),\
_f,\
SA_WSTR(_f)\
)
This macro will receive the _params... from the SA_ASSERT macro and is made to generate additional custom parameters to build the exception (ex: get input parameters' name). The _baseInfo
will always be automatically provided and must be forwarded to the exception.
/!\ Warning: If the exception type is defined in a namespace, it must be specified within the constructor-helper macro (MyNamespace::MyException
).
After including the new exception type, it is ready to be used with the SA_ASSERT macro:
int myInt = 3;
float myFloat = 2.0f;
try
{
SA_ASSERT((MyException, myInt, myFloat), TestChan.MyException, L"optional details!");
}
catch (MyException _exc)
{
// Read values
_exc.i;
_exc.f;
}
[18:24:26][0] {AssertFailure - TestChan.MyException} main.cpp:52 - int __cdecl main(void)
Msg: 'myInt' >= 2 * 'myFloat' => { 3 >= 2 * 2.000000 }: evaluated to false!
Dets: optional details!