6

I work with g++ 4.8.1 and use these two macros for debugging. However, the __func__ macro gives me only the function name, which might be misleading in the case you have many functions with the same name in different classes. The __PRETTY_FUNCTION__ macro produces the whole function signature - with return type, class name and all arguments, which can be very long.

I'd like to have something between - a macro, which will give me only class name and function name. Any way to achieve that?

HEKTO
  • 3,876
  • 2
  • 24
  • 45
  • Assuming you are in a non-static member function, you could use the type of `this`, `typeid` and http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html to get the class name. – Marc Glisse Apr 22 '14 at 20:57
  • 2
    The class name and function name won't always uniquely identify the function. – Keith Thompson Apr 22 '14 at 20:57
  • 1
    @KeithThompson - I can live with that, I don't need 100% precision - it's only debugging – HEKTO Apr 22 '14 at 21:01
  • 1
    I find `__FILE__ "(" STRINGIZE(__LINE__) "): " __func__ " - "` works excellent, _especially_ in MSVC which recognizes this syntax especially. – Mooing Duck Apr 22 '14 at 21:28
  • 1
    By the way, `__func__` is not a macro, that's why it's lowercase. – HolyBlackCat Apr 24 '15 at 21:28

2 Answers2

8

Inspired by this, I created the following macro __COMPACT_PRETTY_FUNCTION__:

std::string computeMethodName(const std::string& function, const std::string& prettyFunction);

#define __COMPACT_PRETTY_FUNCTION__ computeMethodName(__FUNCTION__,__PRETTY_FUNCTION__).c_str() //c_str() is optional


std::string computeMethodName(const std::string& function, const std::string& prettyFunction) {
    size_t locFunName = prettyFunction.find(function); //If the input is a constructor, it gets the beginning of the class name, not of the method. That's why later on we have to search for the first parenthesys
    size_t begin = prettyFunction.rfind(" ",locFunName) + 1;
    size_t end = prettyFunction.find("(",locFunName + function.length()); //Adding function.length() make this faster and also allows to handle operator parenthesys!
    if (prettyFunction[end + 1] == ')')
        return (prettyFunction.substr(begin,end - begin) + "()");
    else
        return (prettyFunction.substr(begin,end - begin) + "(...)");
}

What it does:

  • It takes __PRETTY_FUNCTION__
  • It removes return type and all arguments
  • If the function has zero arguments, it appends (), otherwise (...)

Features:

  • Handles namespaces, constructors and so on
  • Works also with the parenthesis operator!

Limitations:

  • It only works with gcc
  • Created at runtime rather than compile time
  • Heap allocated.
  • Does not work for lambdas, __FUNCTION__ and __PRETTY_FUNCTION__ don't match... I would almost call it a compiler bug :)
    • __FUNCTION__ sees an operator()
    • __PRETTY_FUNCTION__ sees <lambda(...)>
Antonio
  • 19,451
  • 13
  • 99
  • 197
  • 2
    Limitations: Created at runtime rather than compile time, and is heap allocated. – Mooing Duck Apr 24 '15 at 20:19
  • @MooingDuck Is there a way to avoid this, for example with `constexpr` in C++11? Can you help me with that? (In my case it is not so important because used only during debugging). – Antonio Apr 24 '15 at 20:20
  • Well, if you're crafty, you could potentially add something super complicated to place the names into a compile-time _buffer_, but it'd be hard, I probably wouldn't bother. However, I _would_ alter `computeMethodName` to use `const char(&)[N]` as much as possible to reduce the number of heap allocations. I'll whip something up. – Mooing Duck Apr 24 '15 at 20:47
  • 1
    Yours actually seems to work for pretty complex cases too! http://coliru.stacked-crooked.com/a/8d2dd99099c813f0 But not pathalogical cases: http://coliru.stacked-crooked.com/a/6a09d229735cfc72 – Mooing Duck Apr 24 '15 at 21:03
  • 1
    Made a version with zero allocations, though the method name is only valid until the next call in the same thread. I figure that's livable. http://coliru.stacked-crooked.com/a/132eb50d00b4cb7f Doesn't quite get pathalogical cases right, but pretty good. – Mooing Duck Apr 24 '15 at 21:30
  • @MooingDuck Very interesting, thanks! I also seem to understand what you mean with the threading issue :), and yes, it's livable! – Antonio Apr 24 '15 at 21:56
  • @Mathias Interesting! What does `__PRETTY_FUNCTION__` look like for a lambda function? – Antonio Feb 18 '16 at 12:12
  • I guess a regexp would be the simplest for the general case (http://cpp.sh/4wb7p). Of course performance may suffer when solving for the general case. A constexpr solution would be nice. – Mathias Feb 18 '16 at 12:49
  • @Mathias I have updated my answer in any case. I dare to call it a "compiler bug" :) – Antonio Feb 18 '16 at 14:10
2

Unfortunatly, I don't think this can be done easily. I am one of those that don't understand why nobody ever proposed the implementation of a __CLASS__ macro, that could expand to the current class, similarly to all the macros defined by GCC, for example.

I agree that these macros are great help in some difficult debugging situations. Probably difficult to implement.

kebs
  • 6,387
  • 4
  • 41
  • 70