Cleantype
Readable and consistent C++ type introspection - Compiler Decipherer
Install / Use
/learn @pthom/CleantypeREADME
Table of content
<table> <tr><td> <p style="text-align: left;"> <a href="#CleanType-Readable-C++-type-introspection---Compiler-Decipherer">CleanType: Readable C++ type introspection - Compiler Decipherer</a><br/> <a href="#Installation-and-usage">Installation and usage</a><br/> <a href="#About-this-manual">About this manual</a><br/> <a href="#Readable-type-names-and-full-type-names">Readable type names and full type names</a><br/> <a href="#Decipher-compiler-output-and-identify-types-in-the-compiler-output">Decipher compiler output and identify types in the compiler output</a><br/> <a href="#Identify-the-auto-return-type-of-functions-and-functors">Identify the auto return type of functions and functors</a><br/> <a href="#Identify-the-signature-of-lambdas">Identify the signature of lambdas</a><br/> <a href="#Settings---configure-replacements-and-indentation">Settings - configure replacements and indentation</a><br/> <a href="#Compile-time-constexpr-type-names">Compile time constexpr type names</a><br/> <a href="#Decipher-range-v3-auto-types">Decipher range-v3 auto types</a><br/> <a href="#Cheat-sheet">Cheat sheet</a><br/> </p> </tr></td> </table> <img src="https://raw.githubusercontent.com/pthom/cleantype/master/resources/cleantype_logo_small.jpg" align="left" width="200"> <table> <tr> <td> Travis <a href="https://travis-ci.org/pthom/cleantype/"> <img src="https://travis-ci.org/pthom/cleantype.svg?branch=master" /> </a> </td> <td> Windows <a href="https://ci.appveyor.com/project/pthom/cleantype"> <img src="https://ci.appveyor.com/api/projects/status/s6wmhg5q9l69w7aq/branch/master?svg=true" /> </a> </td> <td> License <a href="https://www.boost.org/LICENSE_1_0.txt"> <img src="https://img.shields.io/badge/license-boost%201.0-blue.svg" /> </a> </td> <td> Try this online! <a href="https://mybinder.org/v2/gh/pthom/cleantype/master?filepath=notebooks%2Fcleantype%2Fcleantype.ipynb"> <img src="https://mybinder.org/badge_logo.svg" /> </a> </td> <td> Demo on gitpod <a href="https://gitpod.io/#https://github.com/pthom/cleantype/blob/master/demos/demo_simple.cpp"> <img src="resources/gitpod.jpg" width="50" /> </a> </td> </tr> </table><a href="#Table-of-content"><img src="https://img.shields.io/badge/%3C%20top-E7E7E7.svg" align="right"></a>
CleanType: Readable C++ type introspection - Compiler Decipherer
CleanType is a C++14 header only library which offer readable type names, with a consistent naming scheme across compilers, at run-time and compile-time. It can also output the signature of lambda functions, and the result type of any auto function.
<a href="#Table-of-content"><img src="https://img.shields.io/badge/%3C%20top-E7E7E7.svg" align="right"></a>
TLDR: a quick example for the impatient reader
#include <cleantype/cleantype.hpp>
#include <range/v3/all.hpp>
int main() {
std::set<std::string> v { "Hello", "There"};
// cleantype::full -> full type string (the output will depend on the compiler and on the libc version)
std::cout << cleantype::full(v) << "\n";
// => Outputs: std::set<std::__cxx11::basic_string<char>, std::less<std::__cxx11::basic_string<char>>, std::allocator<std::__cxx11::basic_string<char>>> &
// cleantype::clean -> readable type string (this string is constant across compilers and libc versions)
std::cout << cleantype::clean(v) << "\n";
// Outputs: std::set<std::string> &
// cleantype::show_details -> readable type string together with variable content
std::cout << cleantype::show_details(v) << "\n";
// => Outputs: std::set<std::string> & = [Hello, There]
// cleantype::clean -> can automatically indent deeply nested types (this is optional)
using namespace ranges;
auto squares_take_10 = view::for_each(view::ints(1), [](int x) { return ranges::yield(x * x); }) | view::take(10);
std::cout << cleantype::clean(squares_take_10) << "\n";
// => Outputs:
// ranges::v3::detail::take_exactly_view_<
// ranges::v3::join_view<
// ranges::v3::transform_view<
// ranges::v3::iota_view<
// int,
// void
// >,
// (lambda at example.cpp:19:59)
// >,
// void
// >,
// false
//> &
// cleantype::lambda_clean -> readable signature for lambda functions (generic and non generic lambdas)
auto add = [](auto a, auto b) { return a + b; };
std::cout << cleantype::lambda_clean<std::string, char>(add) << "\n";
// => Outputs: lambda: (std::string, char) -> std::string
}
<a href="https://asciinema.org/a/HDu34hBlRJ8lbHPgvEXvvIqmN?speed=2.8&t=14" target="_blank"><img src="https://asciinema.org/a/HDu34hBlRJ8lbHPgvEXvvIqmN.svg" width="300" align="right" style="padding-left: 10px"/></a> The video to the right gives a 2 minutes overview of the library. This demo uses cling, a fully compliant C++14 REPL, and asciinema, a terminal session recorder. You can pause at any time, and copy-paste samples from it. Its source code is here.
The included tool ct_compiler_decipher simplifies the template noise in your compiler output: just "|" (pipe) your build tool to it.
Cleantype can be seeen as a developper friendly typeid alternative, and as a tool for those who are tired by the template noise in the compiler output.
Motivation
In C++, typeid.name() is able to display the type of variables.
However it has several limitations: const, volatile, &&qualifiers are ignored; it cannot identify the signature of lambdas function, and last but not least, the returned name if often unreadable: for example std::set<std::string> becomes
std::set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >
This library tries to overcomes some of these limitations. It is composed mainly of C++11 / C++14 functions. It also contains some macros in order to be able to display rvalue reference type, as well as variables names. Macros are prepended with a prefix 'CT_'.
The returned types names should be equal (or at least similar) accross compilers.
Status
Note: this library is heavily tested, with clang, gcc and msvc. However, it is subject to quick evolution, and should be considered as a beta version.
More infos
See the introductory blog post
<a href="#Table-of-content"><img src="https://img.shields.io/badge/%3C%20top-E7E7E7.svg" align="right"></a>
Installation and usage
cleantypeis a small header only library, so you just need to clone it and add it to your path. It works with C++ 14 and C++17; and is tested succesfully with gcc (>=5), clang (>=6), appleclang, and msvc (>= MSVC 2017).
Then, include cleantype/cleantype.hpp (this file includes a comprehensive API doc). Alternatively, you can use the "all in one version", which is comprised of only one header file, inside the "include_all_in_one" folder.
Notes:
cleantype can be used as a standalone library. However, in order to use be able to read settings from a preference file, you will need nlohmann/json. If you want to use this feature, define CLEANTYPE_USE_NLOHMANN_JSON before including cleantype.hpp and make sure that nlohmann/json.hpp is in your include path.
ct_compiler_decipheris comprised of a single c++ file. It's compilation can be done viamakeor via$(CXX) -Isrc/include -Ithird_party/FunctionalPlus/include --std=c++14 src/tools/ct_compiler_decipher/ct_compiler_decipher.cpp -o ct_compiler_decipher
<a href="#Table-of-content"><img src="https://img.shields.io/badge/%3C%20top-E7E7E7.svg" align="right"></a>
About this manual
This manual is fully interactive! It was written using cling, xeus cling and jupyter notebook. Cling enables a Read-Eval-Print-Loop (REPL) development mode with C++. This approach benefits a lot from having a good type introspection, which is the aim of this library. I wrote an article which is a "hands-on session" about this for those who are interested.
The code that you read in this manual is real live code that can be executed inside jupyter notebook. You can try it directly inside binder: click on the "launch binder" at the top of this page.<br/> Notes:
- Beware, it may require about 1 minute to load; but then you will be able to run the code live from your browser!
- Inside the notebook, click on the "Run" button in order to execute each cell (in order)
- You can modify and run the code as you desire inside binder!
- Note that there is a limitation in cling that requires that you add two ";" after each lambda function definition
The "#pragma cling add_include_path" is specific to cling. Beside this, everything is standard C++.
// Special macro to change the include path (this is required for the binder demo)
#pragma cling add_include_path("./include")
#include <cleantype/cleantype.hpp>
// The includes below are not required, they are just used for the purpose of this manual
#include <future>
#include <numeric>
#include <fplus/fplus.hpp>
// This macro is used later in this manual in order to display c
