userver: userver/compiler/demangle.hpp Source File
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
demangle.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/compiler/demangle.hpp
4/// @brief @copybrief compiler::GetTypeName
5/// @ingroup userver_universal
6
7#include <chrono>
8#include <string>
9#include <typeindex>
10
11USERVER_NAMESPACE_BEGIN
12
13/// Compiler and C++ language related tweaks
14namespace compiler {
15
16/// Returns a human-readable representation of provided type name.
17std::string GetTypeName(std::type_index type);
18
19namespace detail {
20
21template <typename T>
22constexpr std::string_view GetTypeAlias() {
23 if constexpr (std::is_same_v<T, std::string>) {
24 return "std::string";
25 } else if constexpr (std::is_same_v<T, std::string_view>) {
26 return "std::string_view";
27 } else if constexpr (std::is_same_v<T, std::chrono::nanoseconds>) {
28 return "std::chrono::nanoseconds";
29 } else if constexpr (std::is_same_v<T, std::chrono::microseconds>) {
30 return "std::chrono::microseconds";
31 } else if constexpr (std::is_same_v<T, std::chrono::milliseconds>) {
32 return "std::chrono::milliseconds";
33 } else if constexpr (std::is_same_v<T, std::chrono::seconds>) {
34 return "std::chrono::seconds";
35 } else if constexpr (std::is_same_v<T, std::chrono::minutes>) {
36 return "std::chrono::minutes";
37 } else if constexpr (std::is_same_v<T, std::chrono::hours>) {
38 return "std::chrono::hours";
39 } else if constexpr (std::is_same_v<T, std::chrono::steady_clock::time_point>) {
40 return "std::chrono::steady_clock::time_point";
41 } else if constexpr (std::is_same_v<T, std::chrono::system_clock::time_point>) {
42 return "std::chrono::system_clock::time_point";
43 } else {
44 return {};
45 }
46}
47
48} // namespace detail
49
50#if defined(__GNUC__) && !defined(DOXYGEN)
51
52namespace detail {
53
54template <typename T>
55constexpr std::string_view GetFullTypeName() {
56 constexpr auto alias = GetTypeAlias<T>();
57 if constexpr (!alias.empty()) {
58 return alias;
59 } else {
60 constexpr std::string_view name = __PRETTY_FUNCTION__;
61 constexpr auto begin_pos = name.find("T = ");
62 constexpr auto end_pos = name.find_first_of(";]", begin_pos);
63 return name.substr(begin_pos + 4, end_pos - begin_pos - 4);
64 }
65}
66
67} // namespace detail
68
69template <typename T>
70constexpr std::string_view GetTypeName() {
71 return detail::GetFullTypeName<typename std::decay_t<T>>();
72}
73
74#else // !__GNUC__
75
76/// @brief Returns a human-readable representation of provided type name.
77///
78/// GetTypeName(typeidT)) outputs the type, not the alias. For std::chrono
79/// functions it gives unreadable results:
80/// std::chrono::duration<long, std::ratio<1l, 1l> > - it's `seconds`
81///
82/// The `GetTypeName<T>()` provides a more readable output.
83template <typename T>
85 constexpr auto alias = detail::GetTypeAlias<typename std::decay_t<T>>();
86 if constexpr (!alias.empty()) {
87 return alias;
88 } else {
89 static const auto name = GetTypeName(typeid(T));
90 return name;
91 }
92}
93
94#endif // __GNUC__
95
96} // namespace compiler
97
98USERVER_NAMESPACE_END