CleanType - Readable and consistent C++ type introspection - Compiler Decipherer

CleanType - Readable and consistent C++ type introspection - Compiler Decipherer

CleanType  is a small 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.

The included tool (ct_compiler_decipher) simplifies the template noise in your compiler output: just pipe ("|") your build tool to it.

This project started as a simple "what if" project: I wanted to be able to get more information about the types hidden behind auto variables, lambdas, etc; and I wanted to be able to get this information interactively (e.g. inside a C++ REPL, or from the compiler output).

Features

If you are interested in this project, stop reading here! Instead, go to the full manual which is much more complete and interesting than this introductory article. This manual is also available in a fully interactive version (beware, it may require about 1 minute to load; but then you will be able to run the code live from your browser!)
  • Readable type names
    e.g std::string  
    instead of std::basic_string<char, std::allocator<char>>
  • Readable type names in the compiler error output
    Because no one likes to be punished with template gibberish when trying to correct an error.
  • Identify the auto return type of functions and the signature of lambdas
    Because it is a great way to understand what's going on in the code.
  • Identify types in the compiler output
    Because sometimes we are lost in a forest of auto return types; and we would like the compiler to tell us what he knows (and is hiding from us!)
  • Compile time constexpr type names

Highlights

Below are some non interactive highlights for the impatient reader.

Readable types and signatures

Suppose you have a lambda (cache_int_strings) that will create a sort of cache between the n first integers and their string representation (natural representation, and roman number representation). Using cleantype, you can get its signature like this:

std::cout << cleantype::lambda_clean(cache_int_strings);
==> lamda: (int) -> std::map<int, std::array<std::string, 2>>

or, depending on the indent limit, which is configurable:

lambda: (int) -> std::map< // lambda signature
    int,                   // cleantype can indent the types
    std::array<
        std::string,  // note: cleantype will decipher the type
        2             // (i.e basic_string<char,......>> in this case)
    >
>

You can also print the type and content of any container

auto five_numbers = make_cache_int_strings(5);
std::cout << CT_show_details(five_numbers);

will output

[std::map<
    int,
    std::array<
        std::string,
        2
    >
>] five_numbers = [(1, ["1", "I"]), (2, ["2", "II"]), (3, ["3", "III"]), (4, ["4", "IV"]), (5, ["5", "V"])]

Notes: the full source for this demo is available here. Of course, CleanType handles more than just lambdas, and is able to output any type.

Decipher the compiler output

Suppose you have an error and you are being punished by the compiler. The tool ct_compiler_decipher   can make your life easier. Just pipe your build command line to it:

> clang++ --std=c++14 -c code.cpp 2>&1 | ct_compiler_decipher
code.cpp:10:42: error: invalid operands to binary expression ('std::map<std::string, int> ' and 'int')
    auto add_one = [](auto x) { return x + 1; };
                                       ~ ^ ~

Here, 'std::map<std::__cxx11::basic_string<char>,.... >' was deciphered to std::map<std::string, int>

Miscellaneous remarks and questions

With this project, I am experiencing with a new interactive way of presenting a project manual. I decided not to use a static documentation web pages since the manual provides an auto-generated table of content. Then, I also decided to binder in order to turn this manual into a fully interactive manual (beware, it may require about 1 minute to load). What is your opinion about this? If you are interested in this interactive way of development, you can also read my article about it.

Also I am gathering input concerning the time to load binder: in my experience the load time can vary between 10 seconds and 3 minutes! I do hope that binder gains traction and becomes faster in the near future. What was your mileage?
Note: if your page seems to be stuck during loading, try to reload it after 1 minute (and meanwhile, you can read the manual in the preview).

I do not claim that this library is 100% foolproof: it is still in its infancy, so that you may expect some bugs. However, I still think it is usable and useful.

I did some efforts in order to get readable representations for most of the STL types, but I certainly forgot some aspects. Cleantype is highly configurable, so that I think it could be adapted to most users needs, as long as they are not torturing the compiler with highly complex templates. Please do try the interactive demos: do you see some types for which some additional deciphering would be required?

As you can see, this library is standalone and header-only. It does not depend on clang libtooling. This is a choice because I wanted it to be as simple as possible to adopt, and as portable as possible.
Of course, this means that the compilation time may increase. So, you may as well consider this library as a drop-in solution: just #include "cleantype.hpp" whenever you need it in your cpp file (or inside your C++ REPL), and then remove it once it helped you find the type you were looking for.

Is it worthwhile to try to define a "normalized" string version of a type? In my opinion, the "east-const" vs "west-const" is just the tip of the iceberg. It is a sign that more established "spelling conventions" would be needed, as far as the types are concerned. They should not be enforced by the compiler, but they should exist someway .
Sadly, the C++ ecosystem is heavily fragmented between different cultures, compilers and toolchains. Humans, compilers, libc implementations : everyone disagrees on what should be the normalized string representation of a type. See an interactive analysis here: typesetting : the east vs west pointless holy war?

About Pascal Thomet

I am Pascal Thomet (pthomet -at- gmail -dot- com). I live in Paris, where I was the co-founder of IVS (http://www.activisu.com). I always had an interest in transmitting knowledge, hence this blog.

Comments