Specialize struct ctp::formatter for Type. Provide a function constexpr auto format(Type); returning a tuple like object. The first element must be a format string followed by the arguments.
ctp::forward(value) or ctp::forward(function, arguments...)
Helper to use print/printf in static_assert and template parameters. See Known limitations.
compile-time-printer
usage: compile-time-parser [optionals] [-- program args...]
Compile-time printer - prints variables and types at compile time in C++.
positional arguments:
program the program to compile the source (default: read from stdin)
args the arguments for the command (default: [])
optional arguments:
-h, --help show this help message and exit
--version show program's version number and exit
-r REMOVE, --remove REMOVE
removes matching regex from type info (default: [])
-cr CAPTURE_REMOVE, --capture-remove CAPTURE_REMOVE
removes matching regex but keeps first capture-group from type info (default: [])
--time-point prints time point of each print statement (default: False)
--no-color disables colored error output stream (default: False)
--hide-compiler-log don't print unparsed compiler log (default: False)
--dump-header-file dumps the C++ header file to ctp/ctp.hpp (default: False)
Highlights
Use --time-point to get the time when the print statement has been reached. This can be used for benchmarking.
0:00:00.236446 - Function one evaluated.
0:00:01.238051 - Function two evaluated.
Use -r and -cr to remove unnecessary information from types:
namespaceabc::def {
template<typename T>
structholder {};
}
using H = abc::def::holder<int>;
constexprauto i = ctp::print(ctp::type{}); // "abc::def::holder"
Output with -r "abc::def::":
holder
Output with -cr ".+<(.+)>":
int
How it works
The implementation of print/printf does nothing more than forcing the compiler to generate warnings depending on the passed arguments. The python tool parses the warnings and converts them back to the actually C++ arguments and outputs them (standardized or formatted) to stdout or stderr.
So what does -fpermissive do and why do we use it?
-fpermissive
Downgrade some diagnostics about nonconformant code from errors to warnings. Thus, using -fpermissive will allow some nonconforming code to compile.
The nonconformant code we use in in the implementation is:
constexprboolprint(int i, int j) {
int unused = i << j;
returntrue;
}
constexprauto test = print(10, 34);
10 << 34 will cause an integer overflow which is not allowed, especially in a constant expression. GCC will output the following interesting diagnostic error:
:2:20: error: right operand of shift expression '(10 << 34)' is greater than or equal to the precision 32 of the left operand [-fpermissive]
GCC evaluates the expression i << j and gives a detailed message about the value of i and j. Moreover, the error will recur, even for the same input. Let us all thank GCC for supporting old broken legacy code. With -fpermissive this error becomes a warning and we can continue compiling.
So everything we like to print at compile-time and can be broken down to fundamental types, can be outputted.
Is it undefined behavior? Certainly. Will it format erase your hard drive? Probably not.
Use it only for development and not in production!
Known limitations
Compiler
Since GCC is the only compiler I am aware of with detailed diagnostic warnings to recur, this tool can only work with GCC. Prove me wrong.
Instantiation of static_assert or template parameter
If a CTP statement is used while instantiate an expression triggered by a static_assert or a template parameter, the compilation will fail without a meaningful error message:
The result of a constexpr functions could get cached. If this happens, a CTP statement will only be evaluated once. Try to generate additional noise to prevent this. Especially if this happens in unevaluated context. Add additional changing input to the function call as (template) parameter. Also, GCC >=10 added -fconstexpr-cache-depth=8. Maybe a smaller value solves the issue.
PressurePlate is a multi-agent environment that requires agents to cooperate during the traversal of a gridworld. The grid is partitioned into several rooms, and each room contains a plate and a closed doorway.
I think I briefly saw somewhere use of this project as a way to include limited C++ snippets that are "run" at text generation time without the need for some meta-level build system nonsense. How does one do this?
I also can't get the following to work:
compile-time-printer -- g++ -std=c++20 -I ../include/ -fsyntax-only -fpermissive examples/compile_time_examples.cpp
for https://gitlab.com/anadon/prime_generator_header/-/blob/master/examples/compile_time_examples.cpp
Originally used during Marketplace.tf's open period, this program was used to get the profit of items bought with keys and sold for dollars. Practically useless for me now, but can be used as an example of tkinter.