VCTR
Loading...
Searching...
No Matches
template_arg_string_conversion.h
1/*
2 ==============================================================================
3 DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
5 Copyright 2022- by sonible GmbH.
6
7 This file is part of VCTR - Versatile Container Templates Reconceptualized.
8
9 VCTR is free software: you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License version 3
11 only, as published by the Free Software Foundation.
12
13 VCTR is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Lesser General Public License version 3 for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 version 3 along with VCTR. If not, see <https://www.gnu.org/licenses/>.
20 ==============================================================================
21*/
22
23#pragma once
24
25#include <string_view>
26#include <cstdint>
27
28//==============================================================================
29// Todo: There is quite a bit of repeated, non-generic code in here. It works for
30// our purpose like this, but we would be happy cleaning this up and making it
31// more generic. Contributions that address this are highly welcome!
32//==============================================================================
33
34namespace vctr
35{
37// clang-format off
38template <class T> consteval std::string_view typeName();
39template <> consteval std::string_view typeName<void>() { return "void"; }
40template <> consteval std::string_view typeName<int8_t>() { return "int8_t"; }
41template <> consteval std::string_view typeName<uint8_t>() { return "uint8_t"; }
42template <> consteval std::string_view typeName<int16_t>() { return "int16_t"; }
43template <> consteval std::string_view typeName<uint16_t>() { return "uint16_t"; }
44template <> consteval std::string_view typeName<int32_t>() { return "int32_t"; }
45template <> consteval std::string_view typeName<uint32_t>() { return "uint32_t"; }
46template <> consteval std::string_view typeName<int64_t>() { return "int64_t"; }
47template <> consteval std::string_view typeName<uint64_t>() { return "uint64_t"; }
48// clang-format on
49
50namespace detail
51{
52
53template <class T>
54consteval std::string_view typeNameWrappedInFunctionTemplateName()
55{
56#if VCTR_MSVC
57 return __FUNCSIG__;
58#else
59 return __PRETTY_FUNCTION__;
60#endif
61}
62
63template <class R, class Arg, R (*t) (Arg)>
64consteval std::string_view functionNameWrappedInFunctionTemplateName()
65{
66#if VCTR_MSVC
67 return __FUNCSIG__;
68#else
69 return __PRETTY_FUNCTION__;
70#endif
71}
72
73template <class R, class ArgA, class ArgB, R (*t) (ArgA, ArgB)>
74consteval std::string_view functionNameWrappedInFunctionTemplateName()
75{
76#if VCTR_MSVC
77 return __FUNCSIG__;
78#else
79 return __PRETTY_FUNCTION__;
80#endif
81}
82
83consteval size_t wrappedTypeNamePrefixLength()
84{
85 // We take void as a test type to wrap in the function and see where we actually
86 // find it in the generated string
87 return typeNameWrappedInFunctionTemplateName<void>().find (typeName<void>());
88}
89
90consteval size_t wrappedTypeNameSuffixLength()
91{
92 return typeNameWrappedInFunctionTemplateName<void>().length() - wrappedTypeNamePrefixLength() - typeName<void>().length();
93}
94
95} // namespace detail
96
97template <class T>
98consteval std::string_view typeName()
99{
100 constexpr auto wrappedName = detail::typeNameWrappedInFunctionTemplateName<T>();
101 constexpr auto prefixLength = detail::wrappedTypeNamePrefixLength();
102 constexpr auto suffixLength = detail::wrappedTypeNameSuffixLength();
103 constexpr auto typeNameLength = wrappedName.length() - prefixLength - suffixLength;
104
105 return wrappedName.substr (prefixLength, typeNameLength);
106}
107
108template <class T>
109consteval std::string_view typeName (const T&)
110{
111 return typeName<T>();
112}
113
115template <class R, class Arg, R (*fn) (Arg)>
116consteval std::string_view functionName()
117{
118 constexpr auto wrappedName = detail::functionNameWrappedInFunctionTemplateName<R, Arg, fn>();
119#if VCTR_MSVC
120 constexpr auto prefixLen = wrappedName.find ("functionNameWrappedInFunctionTemplateName<") + 42;
121 constexpr auto postfixLen = wrappedName.rfind (">(void)");
122 constexpr auto onlyTemplateArgs = wrappedName.substr (prefixLen, postfixLen - prefixLen);
123
124 constexpr auto returnTypeName = typeName<R>();
125 constexpr auto returnTypeLen = onlyTemplateArgs.find (returnTypeName) + returnTypeName.size() + 1;
126 constexpr auto onlyTemplateArgsNoReturnType = onlyTemplateArgs.substr (returnTypeLen);
127
128 constexpr auto argTypeName = typeName<Arg>();
129 constexpr auto argTypeLen = onlyTemplateArgsNoReturnType.find (argTypeName) + argTypeName.size() + 1;
130 constexpr auto onlyFunctionSignature = onlyTemplateArgsNoReturnType.substr (argTypeLen);
131
132 constexpr auto argPos = onlyFunctionSignature.find ("(");
133 constexpr auto functionNameLen = argPos - returnTypeLen;
134
135 return onlyFunctionSignature.substr (returnTypeLen, functionNameLen);
136#else
137 constexpr auto prefixLength = wrappedName.find ("&") + 1;
138 constexpr auto postfixPos = wrappedName.rfind ("]");
139 constexpr auto functionNameLength = postfixPos - prefixLength;
140 return wrappedName.substr (prefixLength, functionNameLength);
141#endif
142}
143
145template <class R, class ArgA, class ArgB, R (*fn) (ArgA, ArgB)>
146consteval std::string_view functionName()
147{
148 constexpr auto wrappedName = detail::functionNameWrappedInFunctionTemplateName<R, ArgA, ArgB, fn>();
149
150#if VCTR_MSVC
151 constexpr auto prefixLen = wrappedName.find ("functionNameWrappedInFunctionTemplateName<") + 42;
152 constexpr auto postfixLen = wrappedName.rfind (">(void)");
153 constexpr auto onlyTemplateArgs = wrappedName.substr (prefixLen, postfixLen - prefixLen);
154
155 constexpr auto returnTypeName = typeName<R>();
156 constexpr auto returnTypeLen = onlyTemplateArgs.find (returnTypeName) + returnTypeName.size() + 1;
157 constexpr auto onlyTemplateArgsNoReturnType = onlyTemplateArgs.substr (returnTypeLen);
158
159 constexpr auto argATypeName = typeName<ArgA>();
160 constexpr auto argATypeLen = onlyTemplateArgsNoReturnType.find (argATypeName) + argATypeName.size() + 1;
161 constexpr auto onlyTemplateArgsNoArgA = onlyTemplateArgsNoReturnType.substr (argATypeLen);
162
163 constexpr auto argBTypeName = typeName<ArgB>();
164 constexpr auto argBTypeLen = onlyTemplateArgsNoReturnType.find (argBTypeName) + argBTypeName.size() + 1;
165 constexpr auto onlyFunctionSignature = onlyTemplateArgsNoReturnType.substr (argBTypeLen);
166
167 constexpr auto argPos = onlyFunctionSignature.find ("(");
168 constexpr auto functionNameLen = argPos - returnTypeLen;
169
170 return onlyFunctionSignature.substr (returnTypeLen, functionNameLen);
171#else
172 constexpr auto prefixLength = wrappedName.find ("&") + 1;
173 constexpr auto postfixPos = wrappedName.rfind ("]");
174 constexpr auto functionNameLength = postfixPos - prefixLength;
175 return wrappedName.substr (prefixLength, functionNameLength);
176#endif
177}
178
179} // namespace vctr
The main namespace of the VCTR project.
Definition: Array.h:24
consteval std::string_view functionName()
Returns the name for a function with a single argument.
Definition: template_arg_string_conversion.h:116
consteval std::string_view typeName()
Returns a string containing the templates type name.
Definition: template_arg_string_conversion.h:98