AUI Framework  master
Cross-platform module-based framework for developing C++20 desktop applications
Useful macros

A set of functionality that introduces non-standard syntax which seems like the C++ features. More...

Detailed Description

A set of functionality that introduces non-standard syntax which seems like the C++ features.

Macros

#define AUI_ENTRY
 Application entry point. More...
 
#define AUI_NO_OPTIMIZE_OUT(object)   { auto unused = &object ; }
 Forbids object from being optimized out by compiler. More...
 
#define AUI_MARK_AS_USED(variable)   { (void)variable; }
 Marks the variable as being used. More...
 
#define AUI_PP_CAT(_1, _2)   AUI_PP_INTERNAL_CAT(_1, _2)
 Expands and concatenates the arguments. Constructed macros reevaluate.
 
#define AUI_PP_STRINGIZE(...)   AUI_PP_INTERNAL_STRINGIZE(__VA_ARGS__)
 Expands and stringifies the only argument.
 
#define AUI_PP_EMPTY(...)
 Returns empty. Given a variadic number of arguments.
 
#define AUI_PP_COMMA(...)   ,
 Returns a comma. Given a variadic number of arguments.
 
#define AUI_PP_IDENTITY(_1)   _1
 Returns the only argument.
 
#define AUI_PP_NARG(...)
 Evaluates to the number of arguments after expansion. More...
 
#define AUI_PP_HAS_COMMA(...)
 Returns 1 if the expansion of arguments has an unprotected comma.Otherwise returns 0. More...
 
#define AUI_PP_HEAD(...)   AUI_PP_INTERNAL_HEAD((__VA_ARGS__, unusedArg))
 Returns the first argument.
 
#define AUI_PP_TAIL(...)   AUI_PP_INTERNAL_TAIL((__VA_ARGS__))
 Returns the tail. A variadic list of all arguments minus the first. More...
 
#define AUI_PP_VARIADIC_CALL(_Macro, ...)
 Calls CAT(_Macro, NARG(VA_ARGS))(VA_ARGS) More...
 
#define AUI_PP_IS_EMPTY(...)
 If the arguments after expansion have no tokens, evaluates to 1. Otherwise evaluates to 0. More...
 
#define AUI_PP_IF(_Cond, _Then, _Else)    AUI_PP_CAT(AUI_PP_INTERNAL_IF_, _Cond)(_Then, _Else)
 Evaluates to _Then if _Cond is 1 and _Else if _Cond is 0.
 
#define AUI_PP_GENERIC_IF(_Cond, _Then, _Else)    AUI_PP_REMOVE_PARENS(AUI_PP_IF(_Cond, _Then, _Else))
 Similar to AUI_PP_IF but takes _Then and _Else in parentheses. More...
 
#define AUI_PP_NARG0(...)    AUI_PP_IF(AUI_PP_IS_EMPTY(__VA_ARGS__), 0, AUI_PP_NARG(__VA_ARGS__))
 Evaluates to the number of arguments after expansion. Identifies 'empty' as 0. More...
 
#define AUI_PP_IS_BEGIN_PARENS(...)
 Expands to 1 if the first argument starts with something in parentheses, otherwise to 0. More...
 
#define AUI_PP_IS_ENCLOSED_PARENS(...)
 Expands to 1 is there is only one argument and it is enclosed in parentheses. More...
 
#define AUI_PP_REMOVE_PARENS(...)   AUI_PP_INTERNAL_REMOVE_PARENS __VA_ARGS__
 Remove the parens, requires AUI_PP_IS_ENCLOSED_PARENS(args) => 1.
 
#define AUI_PP_FOR_EACH(_Macro, _Data, _Tuple)
 Expands to _Macro(0, _Data, e1) _Macro(1, _Data, e2) ... _Macro(K -1, _Data, eK) as many of AUI_INTERNAL_NARG0 _Tuple. More...
 
#define AUI_PP_REPEAT(_Macro, _Data, _N)
 Expands to _Macro(0, _Data, ) _Macro(1, _Data, ) ... _Macro(K - 1, _Data, ) More...
 
#define AUI_PP_INC(_i)   AUI_PP_CAT(AUI_PP_INTERNAL_INC_, _i)
 Increments the argument, requires the argument to be between 0 and 15.
 
#define AUI_PP_COMMA_IF(_i)   AUI_PP_CAT(AUI_PP_INTERNAL_COMMA_IF_, _i)
 Returns comma if _i != 0. Requires _i to be between 0 and 15.
 
#define AUI_ASSERT(condition)   AUI_IMPL_ASSERT(condition)
 Asserts that the passed condition evaluates to true. More...
 
#define AUI_ASSERTX(condition, what)   AUI_IMPL_ASSERTX(condition, what)
 Asserts that the passed condition evaluates to true. Adds extra message string. More...
 
#define AUI_ASSERT_NO_CONDITION(what)   AUI_IMPL_FAIL(what)
 Always triggers assertion fail. More...
 
#define AUI_BREAKPOINT()   AUI_IMPL_BREAKPOINT
 Stops program execution in attached debugger as if a breakpoint were set. More...
 
#define AUI_PERFORM_AS_MEMBER(object, lambda)
 Performs multiple operations on a single object without repeating its name. More...
 
#define AUI_DEFER   ARaiiHelper AUI_PP_CAT($AUI_DEFER_at_line_, __LINE__) = [&]
 Defers execution of the next block to the end of current block (RAII scope). More...
 
#define let   ^ [&](const auto& it)
 Performs multiple operations on a single object without repeating its name (in place) This function can be used as an operator on object. More...
 
#define with_style   + ass::PropertyListRecursive
 Allows to define a style to the view right in place. More...
 
#define async   AThreadPool::global() * [=]()
 Executes following {} block asynchronously in the global thread pool. Unlike asyncX, does now allow to set lambda's capture. Lambda's capture is [=]. More...
 
#define asyncX   AThreadPool::global() *
 Executes following {} block asynchronously in the global thread pool. Unlike async, allows to set lambda's capture but you should always specify lambda's capture. More...
 
#define do_once   if(static bool _aui_once = false; (!_aui_once && (_aui_once = true)))
 Executes following function call or {} block once per program execution. More...
 
#define AUI_ASSERT_UI_THREAD_ONLY()   { AUI_ASSERTX((AWindow::current() ? AThread::current() == AWindow::current()->getThread() : AThread::current() == getThread()), "this method should be used in ui thread only."); }
 Asserts that the macro invocation has been performed in the UI thread.
 
#define AUI_ASSERT_WORKER_THREAD_ONLY()   { AUI_ASSERTX(AThread::current() != AWindow::current()->getThread(), "this method should be used in worker thread only."); }
 Asserts that the macro invocation has not been performed in the UI thread.
 

Macro Definition Documentation

◆ async

#define async   AThreadPool::global() * [=]()

Executes following {} block asynchronously in the global thread pool. Unlike asyncX, does now allow to set lambda's capture. Lambda's capture is [=].

Returns
AFuture<T> where T is the return type of the lambda.
Note
When AFuture<T> is destroyed, the corresponding async task is either cancelled or removed from the execution queue. Use AFutureSet or AAsyncHolder to keep multiple AFuture<T> alive.

Example without a return value

auto task = async {
AThread::sleep(1000); // a long task
};
static void sleep(std::chrono::milliseconds duration)
Sleep for specified duration. Most operation systems guarantee that elasped time will be greater than...
Definition: AThread.cpp:207
#define async
Executes following {} block asynchronously in the global thread pool. Unlike asyncX,...
Definition: kAUI.h:329

Example with a return value

auto futureStatus = async {
int status;
...
AThread::sleep(1000); // a long task
...
return status;
};
int status = *futureStatus;

Lambda operators are supported:

auto futureStatus = async mutable noexcept {
int status;
...
AThread::sleep(1000); // a long task
...
return status;
};
int status = *futureStatus;

◆ asyncX

#define asyncX   AThreadPool::global() *

Executes following {} block asynchronously in the global thread pool. Unlike async, allows to set lambda's capture but you should always specify lambda's capture.

Returns
AFuture<T> where T is the return type of the lambda.
Note
When AFuture<T> is destroyed, the corresponding async task is either cancelled or removed from the execution queue. Use AFutureSet or AAsyncHolder to keep multiple AFuture<T> alive.

Example without a return value

auto task = asyncX [&] {
AThread::sleep(1000); // a long task
};
#define asyncX
Executes following {} block asynchronously in the global thread pool. Unlike async,...
Definition: kAUI.h:360

Example with a return value

auto futureStatus = asyncX [&] {
int status;
...
AThread::sleep(1000); // a long task
...
return status;
};
int status = *futureStatus;

◆ AUI_ASSERT

#define AUI_ASSERT (   condition)    AUI_IMPL_ASSERT(condition)

Asserts that the passed condition evaluates to true.

Parameters
conditionthe expression

If the condition evaluates to false, triggers default C++ assert behavior (that is, program termination) on debug build or throws AAssertionFailedException on release builds, so it can be handled and reported properly in production applications.

See also
AUI_ASSERTX
AUI_ASSERT_NO_CONDITION
int v = 2 + 2;
AUI_ASSERT(v >= 0); // does not trigger
AUI_ASSERT(v != 4); // triggers
#define AUI_ASSERT(condition)
Asserts that the passed condition evaluates to true.
Definition: Assert.h:55

◆ AUI_ASSERT_NO_CONDITION

#define AUI_ASSERT_NO_CONDITION (   what)    AUI_IMPL_FAIL(what)

Always triggers assertion fail.

Parameters
whatstring literal which will be appended to the error message

Triggers default C++ assert behavior (that is, program termination) on debug build or throws AAssertionFailedException on release builds, so it can be handled and reported properly in production applications.

See also
AUI_ASSERT
switch (i) {
case 0: // ...
default:
}
#define AUI_ASSERT_NO_CONDITION(what)
Always triggers assertion fail.
Definition: Assert.h:94

◆ AUI_ASSERTX

#define AUI_ASSERTX (   condition,
  what 
)    AUI_IMPL_ASSERTX(condition, what)

Asserts that the passed condition evaluates to true. Adds extra message string.

Parameters
conditionthe expression
whatstring literal which will be appended to the error message

If the condition evaluates to false, triggers default C++ assert behavior (that is, program termination) on debug build or throws AAssertionFailedException on release builds, so it can be handled and reported properly in production applications.

See also
AUI_ASSERT
int v = 2 + 2;
AUI_ASSERTX(v >= 0, "positive value expected"); // does not trigger
AUI_ASSERTX(v != 4, "4 is unacceptable value"); // triggers
#define AUI_ASSERTX(condition, what)
Asserts that the passed condition evaluates to true. Adds extra message string.
Definition: Assert.h:74
Examples
/github/workspace/aui.views/src/AUI/View/AView.h.

◆ AUI_BREAKPOINT

#define AUI_BREAKPOINT ( )    AUI_IMPL_BREAKPOINT

Stops program execution in attached debugger as if a breakpoint were set.

If debugger is not present, behaviour is undefined.

AUI_BREAKPOINT(); // stops debugger here.
#define AUI_BREAKPOINT()
Stops program execution in attached debugger as if a breakpoint were set.
Definition: Breakpoint.h:26

◆ AUI_DEFER

#define AUI_DEFER   ARaiiHelper AUI_PP_CAT($AUI_DEFER_at_line_, __LINE__) = [&]

Defers execution of the next block to the end of current block (RAII scope).

This example prints "Hello world\n":

AUI_DEFER { printf(" world\n") };
printf("Hello");
#define AUI_DEFER
Defers execution of the next block to the end of current block (RAII scope).
Definition: kAUI.h:197
See also
ARaiiHelper

◆ AUI_ENTRY

#define AUI_ENTRY
Value:
AUI_EXPORT int aui_entry(const AStringVector& args); \
AUI_EXPORT int aui_main(int argc, char** argv, int(*aui_entry)(const AStringVector&)); \
int main(int argc, char** argv) { \
return aui_main(argc, argv, aui_entry);\
} \
AUI_EXPORT int aui_entry(const AStringVector& args)
An AVector with string-related functions.
Definition: AStringVector.h:22
API_AUI_CORE const ACommandLineArgs & args() noexcept
Definition: OSAndroid.cpp:29

Application entry point.

Native entry point varies platform to platform (i.e. Windows requires int main entry point for console applications and WinMain for graphical applications; entry point of an Android application is located in Java code). AUI_ENTRY unifies your entry point, efficiently supporting every platform.

AUI_ENTRY of a graphical application should be non-blocking since on mobile platforms application's event loop is located outsize of the entry point. On desktop platforms an event loop is created outside AUI_ENTRY in order to unify the mobile and desktop behaviour. If there are no open windows, the event loop breaks causing the application to exit.

Application arguments (int argc, char** argv) are forwarded to AUI_ENTRY as AStringVector args.

Note
On Android, iOS and macOS only the main thread is able to initialize graphics context.

◆ AUI_MARK_AS_USED

#define AUI_MARK_AS_USED (   variable)    { (void)variable; }

Marks the variable as being used.

Silences the unused variable compiler warning.

Can be used to force [=] lambda to capture a variable.

◆ AUI_NO_OPTIMIZE_OUT

#define AUI_NO_OPTIMIZE_OUT (   object)    { auto unused = &object ; }

Forbids object from being optimized out by compiler.

Parameters
objectTarget object. Can be pointer-to-function, pointer-to-member, any variable.

Performs compiler hacks in order to prevent the compiler/linker from optimizing out the specified object. It's useful for debugging purposes, when the function is expected to exist to be called.

The macro should be called in any function/method which is not being optimized out (i.e. in destructor).

Basic usage:

struct SomeClass {
public:
~SomeClass() {
AUI_NO_OPTIMIZE_OUT(SomeClass::debuggerMethod)
}
int debuggerMethod() {
...
}
}
#define AUI_NO_OPTIMIZE_OUT(object)
Forbids object from being optimized out by compiler.
Definition: macros.h:40
Examples
/github/workspace/aui.core/src/AUI/Traits/iterators.h.

◆ AUI_PERFORM_AS_MEMBER

#define AUI_PERFORM_AS_MEMBER (   object,
  lambda 
)
Value:
struct __apply ## __FUNCTION__ ## __LINE__ : std::decay_t<decltype(object)> { \
void operator()() { \
lambda; \
} \
}; \
(static_cast<__apply ## __FUNCTION__ ## __LINE__ &>(object))()

Performs multiple operations on a single object without repeating its name.

Parameters
objectobject to perform operations on
lambdacode executed in the context of an object (as its member function)
Note
It's an analogue to with, apply in Kotlin.
without with
class Worker {
public:
void buildHouse();
void plantTree();
void raiseSon();
};
...
auto worker = _new<Worker>();
worker->buildHouse();
worker->plantTree();
worker->raiseSon();
class Worker {
public:
void buildHouse();
void plantTree();
void raiseSon();
};
...
auto worker = _new<Worker>();
buildHouse();
plantTree();
raiseSon();
});
#define AUI_PERFORM_AS_MEMBER(object, lambda)
Performs multiple operations on a single object without repeating its name.
Definition: kAUI.h:142

◆ AUI_PP_FOR_EACH

#define AUI_PP_FOR_EACH (   _Macro,
  _Data,
  _Tuple 
)
Value:
AUI_PP_CAT(AUI_PP_INTERNAL_FOR_EACH_IMPL_, AUI_PP_NARG0 _Tuple) \
(0, _Macro, _Data, _Tuple)
#define AUI_PP_CAT(_1, _2)
Expands and concatenates the arguments. Constructed macros reevaluate.
Definition: APreprocessor.h:22
#define AUI_PP_NARG0(...)
Evaluates to the number of arguments after expansion. Identifies 'empty' as 0.
Definition: APreprocessor.h:163

Expands to _Macro(0, _Data, e1) _Macro(1, _Data, e2) ... _Macro(K -1, _Data, eK) as many of AUI_INTERNAL_NARG0 _Tuple.

Requires: * |_Macro| can be called with 3 arguments.

  • |_Tuple| expansion has no more than 15 elements.

◆ AUI_PP_GENERIC_IF

#define AUI_PP_GENERIC_IF (   _Cond,
  _Then,
  _Else 
)     AUI_PP_REMOVE_PARENS(AUI_PP_IF(_Cond, _Then, _Else))

Similar to AUI_PP_IF but takes _Then and _Else in parentheses.

AUI_PP_GENERIC_IF(1, (a, b, c), (d, e, f)) => a, b, c AUI_PP_GENERIC_IF(0, (a, b, c), (d, e, f)) => d, e, f

◆ AUI_PP_HAS_COMMA

#define AUI_PP_HAS_COMMA (   ...)
Value:
AUI_PP_INTERNAL_16TH( \
(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0))

Returns 1 if the expansion of arguments has an unprotected comma.Otherwise returns 0.

Requires no more than 15 unprotected commas.

◆ AUI_PP_IS_BEGIN_PARENS

#define AUI_PP_IS_BEGIN_PARENS (   ...)
Value:
AUI_PP_HEAD(AUI_PP_CAT(AUI_PP_INTERNAL_IBP_IS_VARIADIC_R_, \
AUI_PP_INTERNAL_IBP_IS_VARIADIC_C __VA_ARGS__))
#define AUI_PP_HEAD(...)
Returns the first argument.
Definition: APreprocessor.h:78

Expands to 1 if the first argument starts with something in parentheses, otherwise to 0.

◆ AUI_PP_IS_EMPTY

#define AUI_PP_IS_EMPTY (   ...)
Value:
AUI_PP_INTERNAL_IS_EMPTY(AUI_PP_HAS_COMMA(__VA_ARGS__), \
AUI_PP_HAS_COMMA(__VA_ARGS__()), \
#define AUI_PP_HAS_COMMA(...)
Returns 1 if the expansion of arguments has an unprotected comma.Otherwise returns 0.
Definition: APreprocessor.h:70
#define AUI_PP_COMMA(...)
Returns a comma. Given a variadic number of arguments.
Definition: APreprocessor.h:40

If the arguments after expansion have no tokens, evaluates to 1. Otherwise evaluates to 0.

Requires: * the number of arguments after expansion is at most 15.

  • If the argument is a macro, it must be able to be called with one argument.

Implementation details:

There is one case when it generates a compile error: if the argument is macro that cannot be called with one argument.

#define M(a, b) // it doesn't matter what it expands to

// Expected: expands to 0. // Actual: compile error. AUI_PP_IS_EMPTY(M)

There are 4 cases tested:

  • VA_ARGS possible expansion has no unparen'd commas. Expected 0.
  • VA_ARGS possible expansion is not enclosed in parenthesis. Expected 0.
  • VA_ARGS possible expansion is not a macro that ()-evaluates to a comma. Expected 0
  • VA_ARGS is empty, or has unparen'd commas, or is enclosed in parenthesis, or is a macro that ()-evaluates to comma. Expected 1.

We trigger detection on '0001', i.e. on empty.

◆ AUI_PP_IS_ENCLOSED_PARENS

#define AUI_PP_IS_ENCLOSED_PARENS (   ...)
Value:
AUI_PP_IS_EMPTY(AUI_PP_EMPTY __VA_ARGS__), 0)
#define AUI_PP_IF(_Cond, _Then, _Else)
Evaluates to _Then if _Cond is 1 and _Else if _Cond is 0.
Definition: APreprocessor.h:136
#define AUI_PP_EMPTY(...)
Returns empty. Given a variadic number of arguments.
Definition: APreprocessor.h:34
#define AUI_PP_IS_BEGIN_PARENS(...)
Expands to 1 if the first argument starts with something in parentheses, otherwise to 0.
Definition: APreprocessor.h:170
#define AUI_PP_IS_EMPTY(...)
If the arguments after expansion have no tokens, evaluates to 1. Otherwise evaluates to 0.
Definition: APreprocessor.h:126

Expands to 1 is there is only one argument and it is enclosed in parentheses.

◆ AUI_PP_NARG

#define AUI_PP_NARG (   ...)
Value:
AUI_PP_INTERNAL_16TH( \
(__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))

Evaluates to the number of arguments after expansion.

#define PAIR x, y

AUI_PP_NARG() => 1 AUI_PP_NARG(x) => 1 AUI_PP_NARG(x, y) => 2 AUI_PP_NARG(PAIR) => 2

Requires: the number of arguments after expansion is at most 15.

◆ AUI_PP_NARG0

#define AUI_PP_NARG0 (   ...)     AUI_PP_IF(AUI_PP_IS_EMPTY(__VA_ARGS__), 0, AUI_PP_NARG(__VA_ARGS__))

Evaluates to the number of arguments after expansion. Identifies 'empty' as 0.

#define PAIR x, y

AUI_PP_NARG0() => 0 AUI_PP_NARG0(x) => 1 AUI_PP_NARG0(x, y) => 2 AUI_PP_NARG0(PAIR) => 2

Requires: * the number of arguments after expansion is at most 15.

  • If the argument is a macro, it must be able to be called with one argument.

◆ AUI_PP_REPEAT

#define AUI_PP_REPEAT (   _Macro,
  _Data,
  _N 
)
Value:
AUI_PP_CAT(AUI_PP_INTERNAL_FOR_EACH_IMPL_, _N) \
(0, _Macro, _Data, AUI_PP_INTENRAL_EMPTY_TUPLE)

Expands to _Macro(0, _Data, ) _Macro(1, _Data, ) ... _Macro(K - 1, _Data, )

Empty if _K = 0. Requires: * |_Macro| can be called with 3 arguments.

  • |_K| literal between 0 and 15

◆ AUI_PP_TAIL

#define AUI_PP_TAIL (   ...)    AUI_PP_INTERNAL_TAIL((__VA_ARGS__))

Returns the tail. A variadic list of all arguments minus the first.

Requires at least one argument.

◆ AUI_PP_VARIADIC_CALL

#define AUI_PP_VARIADIC_CALL (   _Macro,
  ... 
)
Value:
AUI_PP_CAT(_Macro, AUI_PP_NARG(__VA_ARGS__))(__VA_ARGS__))
#define AUI_PP_IDENTITY(_1)
Returns the only argument.
Definition: APreprocessor.h:46
#define AUI_PP_NARG(...)
Evaluates to the number of arguments after expansion.
Definition: APreprocessor.h:61

Calls CAT(_Macro, NARG(VA_ARGS))(VA_ARGS)

◆ do_once

#define do_once   if(static bool _aui_once = false; (!_aui_once && (_aui_once = true)))

Executes following function call or {} block once per program execution.

Guarantees that the following code block will be executed only once per application execution.

without with
static bool done = false;
if (!done) {
done = true;
std::printf("Only once!");
}
std::printf("Only once!");
}
#define do_once
Executes following function call or {} block once per program execution.
Definition: kAUI.h:391

◆ let

#define let   ^ [&](const auto& it)

Performs multiple operations on a single object without repeating its name (in place) This function can be used as an operator on object.

Parameters
Tobject type to perform operations on
lambdacode executed in the context of an object (as its member function)
Note
analogue to with, apply in Kotlin

let allows to call methods of newly created objects right in place. For example:

without with
auto tf = _new<ATextField>();
tf->setText("Hello!");
auto tf = _new<ATextField>() let { it->setText("Hello!"); };
#define let
Performs multiple operations on a single object without repeating its name (in place) This function c...
Definition: kAUI.h:262

It's especially useful when building user interfaces:

without with
auto tf1 = _new<ATextField>();
tf1->setText("Hello!");
auto tf2 = _new<ATextField>();
tf2->setText("World!");
...
setContents(Vertical { // confusing
tf1,
tf2,
});
setContents(Vertical { // clean, less code and easy to understand
_new<ATextField>() let { it->setText("Hello!") },
_new<ATextField>() let { it->setText("World!") },
});

◆ with_style

#define with_style   + ass::PropertyListRecursive

Allows to define a style to the view right in place.

#include <AUI/ASS/ASS.h>
using namespace ass;
...
setContents(Centered {
_new<ALabel>("Red text!") with_style { TextColor { AColor::RED } },
});
#define with_style
Allows to define a style to the view right in place.
Definition: kAUI.h:287

Also applicable to declarative-style views:

#include <AUI/ASS/ASS.h>
using namespace ass;
...
setContents(Centered {
Label { "Red text!" } with_style { TextColor { AColor::RED } },
});
Collaboration diagram for Useful macros: