Classes | Macros | Functions
Meta

Utilities for template and preprocessor metaprogramming. More...

Classes

struct  aurora::Type< T >
 Simple type wrapper, can be used for overload resolution. More...
 
struct  aurora::Int< N >
 Simple integer wrapper, can be used for overload resolution. More...
 
struct  aurora::FunctionResult< Signature >
 Find out the return type of a function. More...
 
struct  aurora::FunctionParam< Signature, N >
 Find out the N-th parameter type of a function. More...
 
struct  aurora::FunctionArity< Signature >
 Find out the number of parameters of a function. More...
 
struct  aurora::Typelist< Ts >
 Class template to store a list of types. More...
 
struct  aurora::TypelistAt< Types, Index >
 Random access to type. More...
 
struct  aurora::TypelistFind< Types, Searched >
 Find position of type in typelist. More...
 
struct  aurora::TypelistCat< LhsTypelist, RhsTypelist >
 Concatenate two typelists. More...
 
struct  aurora::TypelistContains< Typelist1, T >
 Check if type is part of typelist. More...
 

Macros

#define AURORA_PP_LIMIT   5
 Limit for preprocessor metaprogramming arguments. More...
 
#define AURORA_PP_CAT(a, b)
 Concatenate two expressions (evaluated ## operator) More...
 
#define AURORA_PP_STRINGIZE(a)
 Convert expression to string (evaluated # operator) More...
 
#define AURORA_PP_IF(condition, trueCase, falseCase)
 Conditional evaluation. More...
 
#define AURORA_PP_ENUMERATE(n, macro)
 Apply a macro repeated times. More...
 
#define AURORA_PP_ENUMERATE_COMMA(n, macro)
 Apply a macro repeated times, comma-separated. More...
 
#define AURORA_PP_COMMA_IF(n)
 Comma if non-zero argument. More...
 
#define AURORA_PP_AT(size, n, tuple)
 Access element of tuple. More...
 
#define AURORA_PP_FOREACH(macro, tuple)
 Apply macro for each element in tuple. More...
 
#define AURORA_PP_FOREACH_DATA(macro, tuple, data)
 Apply macro for each element in tuple, with additional argument. More...
 
#define AURORA_PP_POSITIVE_SIZE(tuple)
 Size of a non-empty preprocessor tuple. More...
 
#define AURORA_PP_SIZE(tuple)
 Size of a preprocessor tuple. More...
 
#define AURORA_ENABLE_IF(...)   , typename std::enable_if<__VA_ARGS__>::type* = nullptr
 SFINAE Enable If Macro for parameter lists. More...
 
#define AURORA_REQUIRE_COMPLETE_TYPE(Type)
 Macro to ensure complete type. More...
 
#define AURORA_AUTO_RETURN(...)   decltype(__VA_ARGS__) { return (__VA_ARGS__); }
 Function declaration with inferred return type. More...
 

Functions

template<typename Result , typename Tuple >
Result * aurora::dynamicGet (Tuple &t, std::size_t i)
 Access tuple with dynamic index. More...
 
template<typename Transformer , typename SrcTuple >
auto aurora::tupleTransform (const SrcTuple &src) -> InferredReturnType Transformer, std::tuple_size< SrcTuple >::value >::apply(src)) template< typename Tuple > auto tupleFront(Tuple &&t) -> InferredReturnType template< typename Tuple > auto tupleBack(Tuple &&t) -> InferredReturnType template< typename T, typename...Us > T &tupleGet(std::tuple< Us... > &tuple)
 Transform one tuple into another. More...
 
template<typename... Ts, typename Function >
void aurora::foreach (Function &&fn)
 Apply function for each type in variadic parameter pack. More...
 
template<typename... Ts, typename Function >
void aurora::foreach (Function &&fn, Ts &&...args)
 Apply function for each value in variadic parameter pack. More...
 

Detailed Description

Utilities for template and preprocessor metaprogramming.

Macro Definition Documentation

#define AURORA_AUTO_RETURN (   ...)    decltype(__VA_ARGS__) { return (__VA_ARGS__); }

Function declaration with inferred return type.

Based on the C++11 trailing return types feature. Since a lot of functions that benefit from trailing return types must repeat the return type by means of decltype, this macro has been written to avoid the code duplication.
Example:

1 template <typename A, typename B>
2 auto sum(A a, B b) -> AURORA_AUTO_RETURN(a + b)
#define AURORA_ENABLE_IF (   ...)    , typename std::enable_if<__VA_ARGS__>::type* = nullptr

SFINAE Enable If Macro for parameter lists.

Usage:

1 template <typename T>
2 void Function(T value
3  AURORA_ENABLE_IF(std::is_integral<T>::value));
#define AURORA_PP_AT (   size,
  n,
  tuple 
)

Access element of tuple.

Parameters
sizeSize of the tuple. Can be inferred using AURORA_PP_SIZE.
nIndex of the element to access, 0 <= n < size
tuplePreprocessor tuple such as (a, b, c)

Returns the n-th element of a tuple.

1 AURORA_PP_AT(3, 0, (a, b, c)) == a
2 AURORA_PP_AT(3, 1, (a, b, c)) == b
3 AURORA_PP_AT(3, 2, (a, b, c)) == c
#define AURORA_PP_CAT (   a,
 
)

Concatenate two expressions (evaluated ## operator)

This macro does the same as the built-in ## preprocessor operator, however the arguments are expanded before concatenation.

1 #define FIRST [evaluated 1st]
2 #define SECOND [evaluated 2nd]
3 #define LAZY_CAT() FIRST ## SECOND
4 #define EXP_CAT() AURORA_PP_CAT(FIRST, SECOND)
5 
6 // Comparison between ## and Aurora's catenation macro
7 LAZY_CAT() // generates FIRSTSECOND
8 EXP_CAT() // generates [evaluated 1st][evaluated 2nd]
#define AURORA_PP_COMMA_IF (   n)

Comma if non-zero argument.

Evaluates to a comma if n is positive, and to nothing if n is zero.

#define AURORA_PP_ENUMERATE (   n,
  macro 
)

Apply a macro repeated times.

Parameters
nNumber of invocations
macroMacro with signature macro(index), where index is a number from 0 to n-1.

Invokes the macro n times, passing it the indices from 0 to n-1 in this order.

1 #define GENERATOR(index) [index]
2 
3 AURORA_PP_ENUMERATE(4, GENERATOR)
4 // generates:
5 [0] [1] [2] [3]
#define AURORA_PP_ENUMERATE_COMMA (   n,
  macro 
)

Apply a macro repeated times, comma-separated.

Parameters
nNumber of invocations
macroMacro with signature macro(index), where index is a number from 0 to n-1.

Invokes the macro n times, passing it the indices from 0 to n-1 in this order. Puts a comma between each invocation.

1 #define GENERATOR(index) [index]
2 
3 AURORA_PP_ENUMERATE_COMMA(4, GENERATOR)
4 // generates:
5 [0], [1], [2], [3]
#define AURORA_PP_FOREACH (   macro,
  tuple 
)

Apply macro for each element in tuple.

Parameters
macroMacro with signature macro(value, index), where value is the current element of the tuple and index is its index as a number from 0 to n-1.
tupleParenthesized tuple, such as (a, b, c). May be empty.

Applies a macro repeated times, passing it every element in a tuple.

1 #define MACRO(value, index) [index]->value
2 #define TUPLE (first, second, third)
3 
4 AURORA_PP_FOREACH(MACRO, TUPLE)
5 // generates:
6 [0]->first
7 [1]->second
8 [2]->third
#define AURORA_PP_FOREACH_DATA (   macro,
  tuple,
  data 
)

Apply macro for each element in tuple, with additional argument.

Parameters
macroMacro with signature macro(value, index, data), where value is the current element of the tuple, index is its index as a number from 0 to n-1, and data is the additional argument being forwarded.
tupleParenthesized tuple, such as (a, b, c). May be empty.
dataAdditional argument to forward.

Applies a macro repeated times, passing it every element in a tuple. Additional data can be specified that doesn't affect the repetition, but is passed to each macro invocation as an additional argument.

1 #define MACRO(value, index, data) [index]->(value, data)
2 #define TUPLE (first, second, third)
3 
4 AURORA_PP_FOREACH_DATA(MACRO, TUPLE, 42)
5 // generates:
6 [0]->(first, 42)
7 [1]->(second, 42)
8 [2]->(third, 42)
#define AURORA_PP_IF (   condition,
  trueCase,
  falseCase 
)

Conditional evaluation.

If condition evaluates to a positive number, then the expression will be replaced with trueCase. If condition is zero, then it will be falseCase.

When you use function style macros for trueCase and falseCase, put the argument list after the invocation, i.e. AURORA_PP_IF(...)(args)

1 AURORA_PP_IF(0, true, false) == false
2 AURORA_PP_IF(1, true, false) == true
3 AURORA_PP_IF(2, true, false) == true
4 AURORA_PP_IF(3, true, false) == true
#define AURORA_PP_LIMIT   5

Limit for preprocessor metaprogramming arguments.

This number is the maximum size of preprocessor tuples and the highest number that can be passed to repetition macros.

#define AURORA_PP_POSITIVE_SIZE (   tuple)

Size of a non-empty preprocessor tuple.

Parameters
tuplePreprocessor tuple such as (a, b, c), of which the size is inferred.

Returns a non-zero number of elements in a tuple. Use this macro whenever you are sure that a tuple will not be empty.

1 AURORA_PP_POSITIVE_SIZE( () ) == undefined
2 AURORA_PP_POSITIVE_SIZE( (a) ) == 1
3 AURORA_PP_POSITIVE_SIZE( (a, b) ) == 2
4 AURORA_PP_POSITIVE_SIZE( (()) ) == 1
#define AURORA_PP_SIZE (   tuple)

Size of a preprocessor tuple.

Parameters
tuplePreprocessor tuple such as (a, b, c), of which the size is inferred.

Returns the number of elements in a tuple. The size inference may fail in special cases with nested macros. If you are sure that a tuple is non-empty, use AURORA_PP_POSITIVE_SIZE instead, which is simpler and more robust.

1 AURORA_PP_SIZE( () ) == 0
2 AURORA_PP_SIZE( (a) ) == 1
3 AURORA_PP_SIZE( (a, b) ) == 2
4 AURORA_PP_SIZE( (()) ) == 1
#define AURORA_PP_STRINGIZE (   a)

Convert expression to string (evaluated # operator)

This macro does the same as the built-in # preprocessor operator, however the argument is expanded before stringization.

1 #define MACRO(expr) [evaluated expr]
2 #define LAZY_STRINGIZE(expr) #expr
3 #define EXP_STRINGIZE(expr) AURORA_PP_STRINGIZE(expr)
4 
5 // Comparison between # and Aurora's stringize macro
6 LAZY_STRINGIZE(MACRO(42)) // generates "MACRO(42)"
7 EXP_STRINGIZE(MACRO(42)) // generates "[evaluated 42]"
#define AURORA_REQUIRE_COMPLETE_TYPE (   Type)

Macro to ensure complete type.

Usage:

1 template <typename T>
2 void CheckedDelete(T* pointer)
3 {
4  AURORA_REQUIRE_COMPLETE_TYPE(T);
5  delete pointer;
6 }

Function Documentation

template<typename Result , typename Tuple >
Result* aurora::dynamicGet ( Tuple &  t,
std::size_t  i 
)

Access tuple with dynamic index.

Usually, you can only access std::tuple by means of std::get<N>, where N must be a constant expression. This function allows you to pass a dynamic index.

Template Parameters
ResultA type to which every element in the tuple is convertible, e.g. pointer to common base class.
Parameters
tThe tuple of which you want to get an element
iThe index of the element, can be known at runtime
template<typename... Ts, typename Function >
void aurora::foreach ( Function &&  fn)

Apply function for each type in variadic parameter pack.

Template Parameters
TsList of types to iterate through. Can also be a single type of aurora::Typelist<...>.
Parameters
fnFunction object with a member function template void operator() ().

For each type T in Ts, the fn's operator() is called with explicit template argument T. Example:

struct Example
{
template <typename T>
void operator() ()
{
std::cout << typeid(T).name() << ' ';
}
};
aurora::foreach<int, float>(Example()); // output: "int float"
template<typename... Ts, typename Function >
void aurora::foreach ( Function &&  fn,
Ts &&...  args 
)

Apply function for each value in variadic parameter pack.

Parameters
fnFunction object with a member function template void operator() (T& value), or C++14 generic lambda. The parameter must be compatible to type T, however pass by value or by (const) (lvalue|rvalue) reference is allowed.
argsArguments to iterate through.

For each argument arg in args, the expression fn(arg) is evaluated. Example:

struct Example
{
template <typename T>
void operator() (const T& arg)
{
std::cout << typeid(T).name() << '=' << arg << ' ';
}
};
aurora::foreach(Example(), 4, 3.25f); // output: "int=4 float=3.25"
template<typename Transformer , typename SrcTuple >
auto aurora::tupleTransform ( const SrcTuple &  src) -> InferredReturnType Transformer, std::tuple_size<SrcTuple>::value>::apply(src) ) template <typename Tuple> auto tupleFront(Tuple&& t) -> InferredReturnType template <typename Tuple> auto tupleBack(Tuple&& t) -> InferredReturnType template <typename T, typename... Us> T& tupleGet(std::tuple<Us...>& tuple)

Transform one tuple into another.

Transforms each element of a tuple using a given function.

Template Parameters
TransformerClass that has a method static R transform(T element) that takes an element of the source tuple and returns a corresponding value of the new tuple. transform() can be a function template to account for different element types.
Parameters
srcInput tuple being transformed.
Returns
Output tuple, result of the transform. Has the same size as src, but possibly different element types.

Example code:

struct ToDouble
{
static double transform(int i)
{
return 2.5 * i;
}
};
auto tuple = std::make_tuple(1, 2, 4);
auto result = aurora::tupleTransform<ToDouble>(tuple);