Prints values and types during compilation!

Overview

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 {
    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{});  // "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:

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:

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

: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);

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

You might also like...
On this repo, you'll find every codes I made during my NSI classes (informatical courses)

👨‍💻 👩‍💻 school-codes On this repo, you'll find every codes I made during my NSI classes (informatical courses) French for now since this repo is d

PressurePlate is a multi-agent environment that requires agents to cooperate during the traversal of a gridworld.
PressurePlate is a multi-agent environment that requires agents to cooperate during the traversal of a gridworld.

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.

Convert three types of color in your clipboard and paste it to the color property (gamma correct)
Convert three types of color in your clipboard and paste it to the color property (gamma correct)

ColorPaster [Blender Addon] Convert three types of color in your clipboard and paste it to the color property (gamma correct) How to Use Hover your mo

Types for the Rasterio package

types-rasterio Types for the rasterio package A work in progress Install Not yet published to PyPI pip install types-rasterio These type definitions

Statistics Calculator module for all types of Stats calculations.

Statistics-Calculator This Calculator user the formulas and methods to find the statistical values listed. Statistics Calculator module for all types

An awesome list of AI for art and design - resources, and popular datasets and how we may apply computer vision tasks to art and design.
An awesome list of AI for art and design - resources, and popular datasets and how we may apply computer vision tasks to art and design.

Awesome AI for Art & Design An awesome list of AI for art and design - resources, and popular datasets and how we may apply computer vision tasks to a

Built with Python programming language and QT library and Guess the number in three easy, medium and hard rolls
Built with Python programming language and QT library and Guess the number in three easy, medium and hard rolls

guess-the-numbers Built with Python programming language and QT library and Guess the number in three easy, medium and hard rolls Number guessing game

Built with Python programming language and QT library and Guess the number in three easy, medium and hard rolls
Built with Python programming language and QT library and Guess the number in three easy, medium and hard rolls

password-generator Built with Python programming language and QT library and Guess the number in three easy, medium and hard rolls Password generator

Cirq is a Python library for writing, manipulating, and optimizing quantum circuits and running them against quantum computers and simulators
Cirq is a Python library for writing, manipulating, and optimizing quantum circuits and running them against quantum computers and simulators

Cirq is a Python library for writing, manipulating, and optimizing quantum circuits and running them against quantum computers and simulators. Install

Comments
  • Add documentation (if possible) on how to integrate CTP C++ code into reStructuredText documents compiled by Sphinx

    Add documentation (if possible) on how to integrate CTP C++ code into reStructuredText documents compiled by Sphinx

    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

    question 
    opened by anadon 2
  • Support unicode

    Support unicode

    constexpr auto test = ctp::printf(
      "┌{0:─^{2}}┐\n"
      "│{1: ^{2}}│\n"
      "└{0:─^{2}}┘\n", "", "Hello, world!", 20);
    

    Should print:

    ┌────────────────────┐
    │   Hello, world!    │
    └────────────────────┘
    
    enhancement cpp python 
    opened by Viatorus 0
Releases(1.1.0)
Build a grocery store management application.

python_projects_grocery_webapp In this python project, we will build a grocery store management application. It will be 3 tier application, Front end:

codebasics 54 Dec 29, 2022
Drug Discovery App Using Lipinski's Rule-of-Five.

Drug Discovery App A Drug Discovery App Using Lipinski's Rule-of-Five. TAPIWA CHAMBOKO 🚀 About Me I'm a full stack developer experienced in deploying

tapiwa chamboko 3 Nov 08, 2022
A Python 3 client for the beanstalkd work queue

Greenstalk Greenstalk is a small and unopinionated Python client library for communicating with the beanstalkd work queue. The API provided mostly map

Justin Mayhew 67 Dec 08, 2022
Freeze your objects in python

gelidum Freeze your objects in python. Latin English Caelum est hieme frigidum et gelidum; myrtos oleas quaeque alia assiduo tepore laetantur, asperna

Diego J. 51 Dec 22, 2022
A community based economy bot with python works only with python 3.7.8 as web3 requires cytoolz

A community based economy bot with python works only with python 3.7.8 as web3 requires cytoolz has some issues building with python 3.10

4 Jan 01, 2022
The semi-complete teardown of Cosmo's Cosmic Adventure.

The semi-complete teardown of Cosmo's Cosmic Adventure.

Scott Smitelli 10 Dec 02, 2022
This script provides LIVE feedback for On-The-Fly data collection with RELION

README This script provides LIVE feedback for On-The-Fly data collection with RELION (very useful to explore already processed datasets too!) Creating

cryoEM CNIO 6 Jul 14, 2022
Solve various integral equations using numerical methods in Python

Solve Volterra and Fredholm integral equations This Python package estimates Volterra and Fredholm integral equations using known techniques. Installa

Matthew Wildrick Thomas 18 Nov 28, 2022
Data Poisoning based on Adversarial Attacks using Non-Robust Features

Data Poisoning based on Adversarial Attacks using Non-Robust Features Usage python main.py [-h] [--gpu | -g GPU] [--eps |-e EPSILON] [--pert | -p PER

Jonathan E. 1 Nov 02, 2021
Ultimate Microsoft Edge Uninstaller!

Ultimate Microsoft Edge Uninstaller

1 Feb 08, 2022
Cairo-integer-types - A library for bitwise integer types (e.g. int64 or uint32) in Cairo, with a test suite

The Cairo bitwise integer library (cairo-bitwise-int v0.1.1) The Cairo smart tes

27 Sep 23, 2022
Simply create JIRA releases based on your github releases

Simply create JIRA releases based on your github releases

8 Jun 17, 2022
Leveraging pythonic forces to defeat different coding challenges 🐍

Pyforces Leveraging pythonic forces to defeat different coding challenges! Table of Contents Pyforces Tests Pyforces Pyforces is a study repo with a c

Igor Grillo Peternella 8 Dec 14, 2022
Генератор отчетов на Python с использованием библиотеки docx для работы с word-файлами и запросов к сервису

Генератор отчетов на Python с использованием библиотеки docx для работы с word-файлами и запросов к сервису

Semyon Esaev 2 Jun 24, 2022
Multitrack exporter for OP-Z

Underbridge for OP-Z Multitrack exporter Description Exports patterns and projects individual audio tracks to seperate folders for use in your DAW. Py

Thomas Herrmann 71 Dec 25, 2022
A python script that will automate the boring task of login to the captive portal again and again

A python script that will automate the boring task of login to the captive portal again and again

Rakib Hasan 2 Feb 09, 2022
This is a Python script to detect rapid upwards price changes (pumps) in a cryptocurrency pairing

A python script to detect a rapid upwards price brekout (pump) in a cryptocurrency pairing, through pandas and Binance API.

3 May 25, 2022
Script to work around some quirks of the blender obj importer

ObjFix 1.0 (WIP) Script to work around some quirks of the blender obj importer Installation Download this repo In Blender, press "Edit" on the top-bar

Red_3D 4 Nov 20, 2021
Monitoring of lake dynamics

slamcore_utils Description This repo contains the slamcore-setup-dataset script. It can be used for installing a sample dataset for offline testing an

10 Jun 23, 2022
monster hunter world randomizer project

mhw_randomizer monster hunter world randomizer project Settings are in rando_config.py Current script for attack randomization is n mytest.py There ar

2 Jan 24, 2022