XTE_ARROW(), XTE_ARROW_RETURN(), XTE_ARROW_IF(), XTE_ARROW_CHOOSE(), XTE_ARROW_CAST(), XTE_ARROW_CTOR()

Defined in header <xte/preproc/arrow.hpp>

Deduplicates the repetition required for defining the body, noexcept specifier, and requires clause of a template function consisting of a single expression.
(i.e. eliminates annoying typing when defining forwarding function templates.)


Definitions

#arrow
#define XTE_ARROW(...) \
	noexcept __VA_OPT__( \
		(noexcept(__VA_ARGS__)) \
		-> decltype(auto) \
		requires(requires { __VA_ARGS__; }) \
	) { return __VA_ARGS__; }

#arrow-return
#define XTE_ARROW_RETURN(...) \
	noexcept __VA_OPT__( \
		(noexcept(__VA_ARGS__)) \
		requires(requires { __VA_ARGS__; }) \
	) { return __VA_ARGS__; }
Same as #arrow but does not specify a trailing return type. Useful for cast operators.

#arrow-if
#define XTE_ARROW_IF(_cond, _then, ...) \
	noexcept(/* ??? */) \
	-> decltype(auto) \
	requires(/* ??? */) \
	{ if constexpr (_cond) { (_then); } return __VA_ARGS__; }
_cond is explicitly cast to bool.

#arrow-choose
#define XTE_ARROW_CHOOSE(_cond, _then, ...) \
	noexcept(/* ??? */) \
	-> decltype(auto) \
	requires(/* ??? */) \
	{ if constexpr (_cond) { return _then; } else { return __VA_ARGS__; } }
_cond is explicitly cast to bool. _then may optionally be wrapped in parentheses.

#arrow-cast
#define XTE_ARROW_CAST(_attr_spec, _arg, ...) /* ??? */
Defines a cast operator.

#arrow-ctor
#define XTE_ARROW_CTOR(_body, ...) \
	noexcept(/* ??? */) \
	requires(/* ??? */) \
	: /* ??? */ \
	{ /* ??? */ }
Accepts a constructor body consisting of, at most, one expression (optionally wrapped in parentheses), followed by a list of things to initialize and what to initialize them with, respectively, in alternating order. Values must be wrapped in two sets of parentheses, unless the intention is to brace-initialize, in which case they must be wrapped in one outer set of parentheses and one inner set of brackets. Wrapping the thing to initialize in one set of parentheses designates it as a base class type, and wrapping it in two sets of parentheses designates it as a pack of base class types. See [Example #1].


Examples

#0
auto add(auto a, auto b) XTE_ARROW(a + b)

struct S {
	void operator+(S) {} // not marked `noexcept`
};

static_assert(noexcept(add(1, 2)));
static_assert(!noexcept(add(S(), S())));
[View in Compiler Explorer]

#1
template<typename T, typename... Ts>
struct X : T, Ts... {
	int x[2];

	X(int a, int b, auto arg, auto... args) XTE_ARROW_CTOR(, // :
		x,({ a, b }), // x { a, b }
		(T),((arg)), // T(arg)
		((Ts)),((args...)) // Ts(args...)...
	) // {}
};

struct A { int a; };
struct B { double b0, b1; };
struct C { double c0, c1; };
static_assert(noexcept(X<A, B, C>(1, 2, 418, 3.14159, 6.28318)));
// : x { 1, 2 }, A(418), B(3.14159, 6.28318), C(3.14159, 6.28318) {}
[View in Compiler Explorer]