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)
Blender Addon for Snapping a UV to a specific part of a Tilemap

UVGridSnapper A simple Blender Addon for easier texturing. A menu in the UV editor allows a square UV to be snapped to an Atlas texture, or Tilemap. P

2 Jul 17, 2022
CEI Natural Disaster Tracking Portal

CEI Natural Disaster Tracking Portal (cc) Climatic Eye of ISCI We are an initiative that conducts studies in the field of Space Science, publishes pro

Baris Dincer 7 Dec 24, 2022
一个可以自动生成PTGen,MediaInfo,截图,并且生成发布所需内容的脚本

Differential 差速器 一个可以自动生成PTGen,MediaInfo,截图,并且生成发种所需内容的脚本 为什么叫差速器 差速器是汽车上的一种能使左、右轮胎以不同转速转动的结构。使用同样的动力输入,差速器能够输出不同的转速。就如同这个工具之于PT资源,差速器帮你使用同一份资源,输出不同PT

Lei Shi 96 Dec 15, 2022
The Begin button and menu for the Meadows operating system. The start button for UNIX/Linux.

By: Seanpm2001, Meadows Et; Al. Top README.md Read this article in a different language Sorted by: A-Z Sorting options unavailable ( af Afrikaans Afri

Sean P. Myrick V19.1.7.2 4 Aug 28, 2022
A framework to create reusable Dash layout.

dash_component_template A framework to create reusable Dash layout.

The TolTEC Project 4 Aug 04, 2022
Files relating to polymtl university

This is a tool I developed quickly, which allows users to visualize class availability by day of the week for a given program at polymtl. The schedule

PN 3 Mar 15, 2022
Unofficial package for fetching users information based on National ID Number (Tanzania)

Nida Unofficial package for fetching users information based on National ID Number made by kalebu Installation You can install it directly or using pi

Jordan Kalebu 57 Dec 28, 2022
Python MQTT v5.0 async client

gmqtt: Python async MQTT client implementation. Installation The latest stable version is available in the Python Package Index (PyPi) and can be inst

Gurtam 306 Jan 03, 2023
Code and data for learning to search in local branching

Code and data for learning to search in local branching

Defeng Liu 7 Dec 06, 2022
A play store search module

A play store search module

Fayas Noushad 5 Dec 01, 2021
Automated Content Feed Curator

Gathers posts from content feeds, filters, formats, delivers to you.

Alper S. Soylu 2 Jan 22, 2022
What Do Deep Nets Learn? Class-wise Patterns Revealed in the Input Space

What Do Deep Nets Learn? Class-wise Patterns Revealed in the Input Space Introduction: Environment: Python3.6.5, PyTorch1.5.0 Dataset: CIFAR-10, Image

8 Mar 23, 2022
A general-purpose wallet generator, for supported coins only

2gen A general-purpose generator for keys. Designed for all cryptocurrencies supporting the Bitcoin format of keys and addresses. Functions To enable

Vlad Usatii 1 Jan 12, 2022
No more support server flooding with questions about unsupported hosting.

No more support server flooding with questions about unsupported hosting.

3 Aug 09, 2021
Coded in Python 3 - I make for education, easily clone simple website.

Simple Website Cloner - Single Page Coded in Python 3 - I make for education, easily clone simple website. How to use ? Install Python 3 first. Instal

Phạm Đức Thanh 2 Jan 13, 2022
Stocks Trading News Alert Using Python

Stocks-Trading-News-Alert-Using-Python Ever Thought of Buying Shares of your Dream Company, When their stock price got down? But It is not possible to

Ayush Verma 3 Jul 29, 2022
Write complicated anonymous functions other than lambdas in Python.

lambdex allows you to write multi-line anonymous function expression (called a lambdex) in an idiomatic manner.

Xie Jingyi 71 May 19, 2022
The refactoring tutorial I wrote for PyConDE 2022. You can also work through the exercises on your own.

Refactoring 101 planet images by Justin Nichol on opengameart.org CC-BY 3.0 Goal of this Tutorial In this tutorial, you will refactor a space travel t

Kristian Rother 9 Jun 10, 2022
Spinning waffle from waffle shaped python code

waffle Spinning waffle from waffle shaped python code Based on a parametric curve: r(t) = 2 - 2*sin(t) + (sin(t)*abs(cos(t)))/(sin(t) + 1.4) projected

Viljar Femoen 5 Feb 14, 2022
A Python script made for the Python Discord Pixels event.

Python Discord Pixels A Python script made for the Python Discord Pixels event. Usage Create an image.png RGBA image with your pattern. Transparent pi

Stanisław Jelnicki 4 Mar 23, 2022