I took a crack, ignoring the obvious caveat that __PRETTY_FUNCTION__
is a propriety GNU convention that can't be counted on for any guarantees in the formatting. My strategy was to start at the last ')', and then do a search for '(' while balancing parenthesis to avoid tricky parameters like function pointers. But then I was able to make this:
struct baz {
template <typename T>
decltype(auto) complex(int y, foo<int(*)()> a) const noexcept {
std::cout << __PRETTY_FUNCTION__ << std::endl;
return 42;
}
};
baz{}.complex<decltype(&biff)>(42, foo<decltype(&bar)>{});
Which produced:
decltype(auto) baz::complex(int, foo<int (*)()>) const [with T = float (*)()]
So, I made a helper function to do a search, balancing []
, <>
, {}
, and ()
, just in case.
constexpr const char* balancedReverseSeek(bool(*predicate)(char), const char* begin, const char* current) {
size_t squareLevel = 0;
size_t carrotLevel = 0;
size_t parenLevel = 0;
size_t braceLevel = 0;
const char* c = current;
for (; c != begin && (!predicate(*c) || squareLevel || carrotLevel || parenLevel || braceLevel); --c) {
switch (*c) {
case ')':
parenLevel++;
break;
case '(':
parenLevel--;
break;
case ']':
squareLevel++;
break;
case '[':
squareLevel--;
break;
case '>':
carrotLevel++;
break;
case '<':
carrotLevel--;
break;
case '}':
braceLevel++;
break;
case '{':
braceLevel--;
break;
}
}
return c;
}
Then this seems to work ok, and it gets the class name (baz::complex
):
constexpr std::string_view getName(std::string_view prettyName) {
if (prettyName.empty()) {
return prettyName;
}
const char* signatureEnd = prettyName.data() + (prettyName.size() - 1);
const char* paramEnd = balancedReverseSeek([](char c) { return c == ')'; }, prettyName.data(), signatureEnd);
if (paramEnd != prettyName.data()) {
paramEnd--;
}
const char* nameEnd = balancedReverseSeek([](char c) { return c == '('; }, prettyName.data(), paramEnd);
if (nameEnd != prettyName.data()) {
nameEnd--;
}
const char* nameBegin = balancedReverseSeek([](char c) { return c == ' '; }, prettyName.data(), nameEnd);
return { nameBegin, nameEnd - nameBegin + 1 };
}
Demo: https://godbolt.org/z/W578vP
(args...)
to being()
. Since this is a mutating operation, and this is in aconstexpr
context in C++11, the only way you will be able to accomplish this is with constructing a new string containing the name of the function name by building it in a variadic pack expansion (e.g. as an array of characters) -- which won't be easy. Why exactly do you need this functionality? – Human-Compilerconst char*
or evenstd::map<int, const char*>
, soremoveType
as shown is unreliable. – Tony Delroy