views:

1379

answers:

9

I'm currently working on some logging code that supposed to - among other things - print information about the calling function. This should be relatively easy, standard C++ has a type_info class. This contains the name of the typeid'd class/function/etc. but it's mangled. It's not very usefull. I.e. typeid(std::vector).name() returns "St6vectorIiSaIiEE".

Is there a way to produce something usefull from this? Like 'std::vector' for the above example. If it only works for non-template classes, that's fine too.

The sollution should work for gcc, but it would be better if I could port it. It's for logging so it's not so important that it can't be turned of, but it should be helpfull for debugging.

+3  A: 

It's implementation defined, so it's not something that's going to be portable. In MSVC++, name() is the undecorated name, and you have to look at raw_name() to get the decorated one.
Just a stab in the dark here, but under gcc, you might want to look at demangle.h

Eclipse
A: 

I've always wanted to use type_info, but I'm sure that the result of the name() member function is non-standard and won't necessarily return anything that can be converted to a meaningful result.
If you are sticking to one compiler, there maybe a compiler specific function that will do what you want. Check the documentation.

quamrana
A: 

Take a look at __cxa_demangle which you can find at cxxabi.h.

CesarB
I took, it's deprecated, according to the message I get.
terminus
+5  A: 

This is what we use. HAVE_CXA_DEMANGLE is only set if available (recent versions of GCC only).

#ifdef HAVE_CXA_DEMANGLE
const char* demangle(const char* name)
{
   char buf[1024];
    unsigned int size=1024;
    int status;
    char* res = abi::__cxa_demangle (name,
                                 buf,
                                 &size,
                                 &status);
    return res;
  }
#else
const char* demangle(const char* name)
{
  return name;
}
#endif
KeithB
You need to include `#include <cxxabi.h>`.
fuenfundachtzig
+4  A: 

Not a complete solution, but you may want to look at what some of the standard (or widely supported) macro's define. It's common in logging code to see the use of the macros:

__FUNCTION__
__FILE__
__LINE__

e.g.:

log(__FILE__, __LINE__, __FUNCTION__, mymessage);
luke
Not to mention __PRETTY_FUNCTION__.
CesarB
This will give you the information about where you are in the code. What the question was asking was a pretty name of a type, like std::vector.
KeithB
He mentioned it was for debugging, and I stated it wasn't a complete solution. Other macros such as __FUNCDNAME__ will return the decorated name.
luke
Actually, re-reading the question, it was "I'm currently working on some logging code that supposed to - among other things - print information about the calling function." This works.
Max Lybbert
It's not complete, since I don't know the namespace. This is allready in my code. But thanks anyway.
terminus
+3  A: 

Here, take a look at type_strings.cpp it contains a function that does what you want.

If you just look for a demangling tool, which you e.g. could use to mangle stuff shown in a log file, take a look at c++filt, which comes with binutils. It can demangle C++ and Java symbol names.

Johannes Schaub - litb
Just to note, both cxa_demange() (which the code linked to uses) and cx++filt are gcc specific. There is no portable way to do this.
KeithB
c++filt doesn't cut it, I need this stuff (or most of it) at compile-time, mostly done with macros.
terminus
+1  A: 

I also found a macro called _ _ PRETTY _ FUNCTION _ _, which does the trick. It gives a pretty function name (figures :)). This is what I needed.

I.e. it gives me the following:

virtual bool mutex::do_unlock()

But I don't think it works on other compilers.

terminus
Yes, __PRETTY_FUNCTION__ is gcc specific.
Greg Rogers
A: 

Consider using an existing logging library, like log4cxx, instead of writing your own. It handles, among other things, outputting the location of each log line in your desired format. And much more.

Assaf Lavie
A: 
// KeithB's solution is good, but has one serious flaw in that unless buf is static
// it'll get trashed from the stack before it is returned in res - and will point who-knows-where
// Here's that problem fixed, but the code is still non-re-entrant and not thread-safe.
// Anyone care to improve it?

#include <cxxabi.h>

// todo: javadoc this properly
const char* demangle(const char* name)
{
    static char buf[1024];
    size_t size = sizeof(buf);
    int status;
    // todo:
    char* res = abi::__cxa_demangle (name,
                                 buf,
                                 &size,
                                 &status);
    buf[sizeof(buf) - 1] = 0; // I'd hope __cxa_demangle does this when the name is huge, but just in case.
    return res;
  }
Daniel P. Pflager