All Projects → Viatorus → compile-time-printer

Viatorus / compile-time-printer

Licence: BSL-1.0 license
Prints values and types during compilation!

Programming Languages

python
139335 projects - #7 most used programming language
javascript
184084 projects - #8 most used programming language
C++
36643 projects - #6 most used programming language
HTML
75241 projects
SCSS
7915 projects
CMake
9771 projects
shell
77523 projects

Projects that are alternatives of or similar to compile-time-printer

Ibm Z Zos
The helpful and handy location for finding and sharing z/OS files, which are not included in the product.
Stars: ✭ 198 (+340%)
Mutual labels:  print
vastringify
Type-safe Printf in C
Stars: ✭ 60 (+33.33%)
Mutual labels:  printf
Fmt
A modern formatting library
Stars: ✭ 12,698 (+28117.78%)
Mutual labels:  printf
Icecream
🍦 Never use print() to debug again.
Stars: ✭ 5,601 (+12346.67%)
Mutual labels:  print
printfTester
Tester for the ft_printf project of 42 school
Stars: ✭ 94 (+108.89%)
Mutual labels:  printf
bigbug
Easy Microcontroller Debugging Tool
Stars: ✭ 37 (-17.78%)
Mutual labels:  printf
Godbg
Go implementation of the Rust `dbg` macro
Stars: ✭ 172 (+282.22%)
Mutual labels:  print
Stuff
A collection of Swift code 'snippets' that are too small to create a library for and which do not fit in an other library.
Stars: ✭ 41 (-8.89%)
Mutual labels:  print
arduino-printf
Add printf support to the Arduino SDK
Stars: ✭ 64 (+42.22%)
Mutual labels:  printf
Nanolog
Nanolog is an extremely performant nanosecond scale logging system for C++ that exposes a simple printf-like API.
Stars: ✭ 1,710 (+3700%)
Mutual labels:  printf
Icecream Cpp
🍦 Never use cout/printf to debug again
Stars: ✭ 225 (+400%)
Mutual labels:  print
Codeprinter
🖨️ Print out code easily
Stars: ✭ 233 (+417.78%)
Mutual labels:  print
lwprintf
Lightweight printf library optimized for embedded systems
Stars: ✭ 98 (+117.78%)
Mutual labels:  printf
Cypress Terminal Report
Better terminal and file output for cypress test logs.
Stars: ✭ 200 (+344.44%)
Mutual labels:  print
debugging
Improve your Print Debugging
Stars: ✭ 41 (-8.89%)
Mutual labels:  print
Clawpdf
Open Source virtual PDF printer for Windows // Print to PDF, PDF/A, PDF/X, PNG, JPEG, TIF and text
Stars: ✭ 183 (+306.67%)
Mutual labels:  print
ftprintfdestructor
A script that destroys the school 42 project ft_printf
Stars: ✭ 20 (-55.56%)
Mutual labels:  printf
json-peek
Stringify JSON *just enough* to see what it is
Stars: ✭ 33 (-26.67%)
Mutual labels:  print
alog
Update: use loguru instead. Simple straight logging your Python code
Stars: ✭ 38 (-15.56%)
Mutual labels:  print
pwnscripts
Very simple script(s) to hasten binary exploit creation
Stars: ✭ 66 (+46.67%)
Mutual labels:  printf

compile-time printer

Github Releases PyPI Conan Build Status Try online

Compile-Time Printer

Compile-Time Printer prints values and types at compile-time in C++.

Teaser

test.cpp compile-time-printer -- make test.cpp
#include <ctp/ctp.hpp>

template<auto I>
constexpr auto func(int i) {

  // Formatted output.
  ctp::printf("Hello {}!\n", ctp::type{I});

  // Standardized output.
  ctp::print(I + i, sizeof(I));

  return true;
}

constexpr auto test = func<22>(20);
.





Hello int!


42 4




                                          .

Try it out online: https://viatorus.github.io/compile-time-printer/

Overview

Installation

Requires:

  • Python >=3.6
  • GCC >=7.4 and STD >=C++17

To get started, install the python tool:

pip install compile-time-printer

Afterwards, dump the CTP header file and include it in your project:

compile-time-printer --dump-header-file

Alternative, you can install the header file via the conan package.

Finally, run CTP with your build command.

E.g. with g++ directly:

compile-time-printer -- g++ -I. -fsyntax-only -std=c++17 -fpermissive test.cpp

E.g. with make:

compile-time-printer -- make test.cpp

You have to set the compiler flag -fpermissive in order to make it work.

API

ctp.hpp

  • ctp::print( [file descriptor,] arguments )

Prints all arguments in a simple, standardized format. Each argument is separated by one space, ending with a line break.

int x = 42;
ctp::print("Hello", 2.72, x);  // "Hello 2.72 42\n"
  • ctp::printf( [file descriptor,] format, arguments )

Formats and prints all arguments in the desired format without implicit line break. Uses the pythons format string syntax.

int x = 42;
ctp::printf("{:.1f}", 3.14);  // "3.1"
ctp::printf("int: {0:d}; hex: {0:x};\n"    // "int: 42; hex: 2a;\n"
            "oct: {0:o}; bin: {0:b}", x);  // "oct: 52; bin: 101010"
  • ctp::stdout or ctp::stderr

Available file descriptor to print to standard output stream or standard error stream.

ctp::print(ctp::stdout, "Info");  // stdout: "Info\n"
ctp::printf(ctp::stderr, "Warning!\n");  // stderr: "Warning!\n"
  • ctp::type< Types >{} or ctp::type{ variables }

Helper object which can be passed as an argument to print/printf to output the type of the variables rather then their values.

int x = 42;
ctp::print(ctp::type<float>{}, ctp::type{x});  // "float int&\n"
  • ctp::view( data begin, data end ) or ctp::view( data begin, data length ) or ctp::view( contiguous range ) (implicit constructed)

Helper object which can be passed as an argument to print/printf to output a contiguous range.

int a[] = {1, 2, 3};
ctp::print(ctp::view{a, 1}, ctp::view{a + 1, a + 3}, a);  // "[1] [2, 3] [1, 2, 3]\n"
  • ctp::formatter< Type >

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.

struct FooBar {
    int i;
};

template<>
struct ctp::formatter<FooBar> {
    static constexpr auto format(const FooBar& obj) {
        return std::tuple{".i = {}", obj.i};
    }
};

constexpr auto test = ctp::print(FooBar{42});  // ".i = 42"
  • 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:
namespace abc::def {
    template<typename T>
    struct holder {};
}

using H = abc::def::holder<int>;
constexpr auto i = ctp::print(ctp::type<H>{});  // "abc::def::holder<int>"

Output with -r "abc::def::":

holder<int>

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:

constexpr bool print(int i, int j) {
    int unused = i << j;
    return true;
}

constexpr auto 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:

<source>: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:

<source>:55:19: error: non-constant condition for static assertion
    55 | static_assert(test());
       |               ~~~~^~

Because -fpermissive is a legacy option, it is not fully maintained anymore to work across all compile-time instantiation.

One workaround is to forward the expression to a constexpr variable instantiation:

static_assert(ctp::forward<func()>);

Check out this example.

Caching

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.

Check out this example.

License

BSD-1 LICENSE

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].