Awesome
type_name_pp
C++ templates for pretty-printing type names and 'auto' names
<details><summary>Copyright © 2019 Will Wray. Distributed under the Boost Software License, V1.0</summary>Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
Also at boost.org and accompanying file LICENSE_1_0.txt
</details>C++17. Targets GCC, Clang, MSVC.
Namespaceltl
.
Depends onltl
libntbs.hpp
for constexpr C-string slicing.
Uses non-standard, non-portable 'pretty function' compiler extensions.
Tested with recent compilers only.
Variable templates type_name_pp
and auto_name_pp
are defined in namespace ltl
,
taking type T
and auto v
template arguments:
ltl::type_name_pp<T>; // 'Pretty print' name for type T.
ltl::auto_name_pp<v>; // 'Pretty print' output for auto/NTTP value v.
The result is a 'constexpr C-string', a null-terminated char array class type that is
usable as a generic char[N]
(including decay-to-pointer, for const values only).
For convenience, _pu
versions return the string that follows any final "::
" separator:
ltl::type_name_pu<T>; // type name with leading qualifiers stripped.
ltl::auto_name_pu<v>; // auto name with leading qualifiers stripped.
The names are sliced from preprocessor 'pretty function' extensions:
__FUNCSIG__ on MSVC
__PRETTY_FUNCTION__ on GCC, Clang
These are constexpr-usable strings of unspecified format that differs between compilers
and between releases of a compiler;
this method is not backward or forward compatible.
This library does not provide portable names.
Test for your use-case and target platforms.
Usage examples
Simple fundamental type int
:
puts( ltl::type_name_pp<int> ); // Outputs "int"
Namespace-scope struct
type (an incomplete struct type here):
namespace Hello { struct World; }
puts( ltl::type_name_pp<Hello::World> );
// Outputs "Hello::World" on GCC & Clang
// or "struct Hello::World" on MSVC
Use decltype(expr)
to query the type of an expression such as a variable:
const volatile char abc[1][2][3]{};
std::cout << type_name_pp<decltype(abc)>;
Outputs:
"const volatile char[1][2][3]"
on GCC9
"char const volatile[1][2][3]"
on Clang8
"volatile const char[1][2][3]"
on MSVC 19.22.xxxxx
String splicing
The output may include nested name qualifiers for scoped types and ids.
'type_name_pu
' and 'auto_name_pu
' help to 'unqualify' simple names.
Templated types may list their template arguments, recursively...
For more complex name-string-splicing, the included ntbs
lib provides
function templates cat(C-strings...)
and cut<B,E>(C-string)
where B,E
are signed-integer indices for the range [B,E)
:
- Positive values index forward from begin index 0 as usual.
- Negative values index backward from the end of the char array
(-1 serves as end index here as all arrays are zero-terminated).
Design notes
As noted, 'pretty function' output is fickle. I've observed that most changes
between versions of a compiler affect the start of the output, the 'prefix',
while the end of the output, the 'suffix', has stayed relatively stable.
The library functions assume a fixed suffix string and adapt to prefix changes
by comparing with a call for type int
or value 0
.
The returned char array type has an implicit conversion (for const values only)
to its contained built-in char array, which itself decays to const char*
.
This implicit conversion to char array is convenient for compatibility with:
- C-style function interfaces that accept
char*
arguments - C++ std algorithms and range-for loops via
<iterator>
interface
Build
Be sure to keep the copyright and license with any copy of the library header
as well as the GitHub repo link.
As a single header lib there's really nothing to build.
The only dependency is the ntbs
single-header library.
A simple Meson build script is provided which will automatically clone ntbs
(assuming network access) as a git submodule subproject.
Example with default ninja backend:
meson build
ninja -C build
On Windows, Meson can target various backends including vs2019.
An MSI installer for Meson and Ninja is available on the Meson GitHub release page.
The meson build compiles a test file with static asserts that are likely to fail
on any slightly different platform.
Linux Travis | Windows Appveyor |
---|---|
gcc-9, clang-7<br>-std=c++17 | MSVC 19.21.27702.2<br>/std:c++latest |