This question describes how to use __PRETTY_FUNCTION__
to get a full name of a function, including its return type, argument types, namespace and template parameters.
Consider the following, beautiful function:
namespace foo {
namespace {
template<int i>
int (*bar(int (*arg)(int *)))(int *) {
printf("%s\n", __PRETTY_FUNCTION__);
return arg;
}
} // anonymous namespace
} // namespace foo
If it's not obvious to you, the function takes, and returns, a pointer to an int *
-> int
function.
Its pretty name is, when compiled with g++
(4.9),
int (* foo::{anonymous}::bar(int (*)(int*)))(int*) [with int i = 1337]
and, with clang++
(3.5),
int (*foo::(anonymous namespace)::bar(int (*)(int *)) [i = 1337])(int *)
Those strings are pretty unsuitable for testing whether the function is part of a certain namespace. Is there any other way, or, say, a compiler-provided library to parse those strings?
To clarify, I'd rather have something like
foo::{anonymous}::bar <I don't care about anything beyond this point>
Even more ideally, I'd like a compile-time way, such as a constexpr
function split(__PRETTY_FUNCTION__)
that yields some sort of list of
etc, but I'd be happy with just the fully-qualified function name.
After a more careful observation I wrote this code:
template <typename InputIterator, typename T>
InputIterator findClosing( InputIterator first, InputIterator last, T close )
{
if (first == last)
return last;
auto open = *first;
unsigned counter = 1;
while (++first != last)
{
if (*first == close && --counter == 0)
return first;
if (*first == open)
++counter;
}
return last;
}
template <std::size_t N,
std::size_t N2>
std::string f(char const(&str)[N], char const(&name)[N2])
{
using namespace std;
// Argument to isalnum must be unsigned:
auto cond = [] (unsigned char c) {return !isalnum(c) && c != '_';};
auto iter = str;
for (;;++iter)
{
iter = search( iter, end(str),
begin(name), end(name)-1 );
if (iter == end(str))
throw invalid_argument("");
if ((iter == begin(str) || cond(iter[-1]))
&& (iter == end(str) - N2 || (cond(iter[N2-1]) && iter[N2-1] != ':')))
break;
}
auto origin_iter = iter;
while(iter != begin(str))
{
--iter;
for (auto p : {"()", "{}"})
if (*iter == p[1])
iter = findClosing(reverse_iterator<char const*>(iter+1),
reverse_iterator<char const*>(begin(str)),
p[0]).base()-2;
if (cond(*iter) && *iter != ':')
return string(iter+1, origin_iter+N2-1);
}
return string(iter, origin_iter+N2-1);
}
It should work with any function, assuming no unnecessary whitespace is existent in __PRETTY_FUNCTION__
and __func__
contains solely the unqualified function name.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With