__ ___
/\ \__/\_ \
_____ _____ __ __\ \ ,_\//\ \
/\ '__`\/\ '__`\/\ \/\ \\ \ \/ \ \ \
\ \ \_\ \ \ \_\ \ \ \_\ \\ \ \_ \_\ \_
\ \ ,__/\ \ ,__/\ \____/ \ \__\/\____\
\ \ \ \ \ \ \/___/ \/__/\/____/
\/_/ \/_/
pputl Preprocessor Utilities
About
pputl is a C++ preprocessor utilities library. It provides basic preprocessor tools
such as concatenation of multiple symbols, control flow, integer manipulation, etc.
It utilizes a reduce mechanism for some of the logic; see below for more info.
Currently, it uses __VA_OPT__, so a supportive compiler is required (or C++20).
Future releases may ship with a build script for generating the project without this requirement.
Requirements
- C++20 (or
__VA_OPT__ support)
Usage
This is a header-only library; include the include/ directory for access.
install
# copies headers to ${DESTDIR}${PREFIX}/include/pputl/
make install
use
#define THREE PPUTL_SUM(1, 1, 1)
#if PPUTL_NEQ(THREE, 3)
static_assert(false);
#endif
#define MULTICAT PPUTL_CAT(my, cool, cat) // mycoolcat
#define SUM_REDUCER(accum, val, i) PPUTL_ADD(accum, val)
#define SUM(...) PPUTL_REDUCE(SUM_REDUCER, 0, __VA_ARGS__)
#define SEVEN SUM(1, 2, 4)
Tools
pputl comes with a reduce macro generator in the tools/ folder.
This script generates a set of macros that allow for pseudo-recursive value reduction.
Due to the inability for the preprocessor to recurse (without special, [slow!] expansion logic),
it's necessary to generate a new set of macros if REDUCE call chaining is desired.
Output is sent to stdout.
# node genReduceMacro [NAMESPACE] [PREFIX=REDUCE] [STACK_DEPTH=256] [DETAIL=true]
node tools/genReduceMacro NS REDUCE 4 false # true makes entry macro name NS_DETAIL_REDUCE
#define NS_REDUCE(reducer, initial, ...) \
NS_DETAIL_REDUCE_CHOOSER(__VA_ARGS__) \
(reducer, initial, (0, 1, 2, 3)__VA_OPT__(, ) __VA_ARGS__)
#
#define NS_DETAIL_REDUCE_CAT_X(a, b) a##b
#define NS_DETAIL_REDUCE_CAT(a, b) NS_DETAIL_REDUCE_CAT_X(a, b)
#
#define NS_DETAIL_REDUCE_FIRST(i, ...) i
#define NS_DETAIL_REDUCE_REST(_, ...) __VA_ARGS__
#/* */ // clang-format off
#define NS_DETAIL_REDUCE_0(r, a, is) a
#define NS_DETAIL_REDUCE_1(r, a, is, v) r(a, v, NS_DETAIL_REDUCE_FIRST is)
#define NS_DETAIL_REDUCE_2(r, a, is, v, ...) NS_DETAIL_REDUCE_1(r, r(a, v, NS_DETAIL_REDUCE_FIRST is), (NS_DETAIL_REDUCE_REST is), __VA_ARGS__)
#define NS_DETAIL_REDUCE_3(r, a, is, v, ...) NS_DETAIL_REDUCE_2(r, r(a, v, NS_DETAIL_REDUCE_FIRST is), (NS_DETAIL_REDUCE_REST is), __VA_ARGS__)
#/* */ // clang-format on
#define NS_DETAIL_REDUCE_CHOICE(_3, _2, _1, size, ...) \
NS_DETAIL_REDUCE_CAT(NS_DETAIL_REDUCE_, size)
#
#define NS_DETAIL_REDUCE_CHOOSER(...) \
NS_DETAIL_REDUCE_CHOICE(__VA_ARGS__ __VA_OPT__(, ) 3, 2, 1, 0)
The reducing control flow is capable of perfoming any kind of operation,
but other types (e.g. transform) may be useful. More generation scripts may be added here.
Testing
All API features are statically tested with jpcx/cctest
Contributing
Contribution is welcome! Please make a pull request.
I'd like to maximize the utility of the preprocessor, especially in the wake of __VA_OPT__.
Documentation
Project documentation is generated by Doxygen and is hosted by GitHub Pages.