The inner working of #defines that call methods - c++

I know that defines in the beginning of a C++ file are Preprocessor directives so "the preprocessor is executed before the actual compilation of code begins, therefore the preprocessor digests all these directives before any code is generated by the statements [1]".
Now what if I have this simple example:
#define PRINT(function) printFnctionName(#function)
void printFnctionName(string name)
{
cout << name;
}
void test(){};
int main(int argc, char *argv[])
{
PRINT(test);
}
So now my question is really how does the precompiler know what function will be passed in? and how is the pre-compilation/linking/compilation really happening?
Also, the reason I am using define and not a regular function, it is because I wasn't able to find a way to replicate this functionality `#function to retrieve the name of a function

So now my question is really how does the precompiler know what
function will be passed in? and how is the
pre-compilation/linking/compilation really happening?
Preprocessor doesn't know about anything. It simply replaces the text with the defined value and stringifies the value you passed in.
So the compiler sees it:
void printFnctionName(string name)
{
cout << name;
}
void test(){};
int main(int argc, char *argv[])
{
printFnctionName("test");
}

The preprocessor does text substitution. In your case, your code will be transformed to:
int main(int argc, char *argv[])
{
printFnctionName("test");
}
by the preprocessor before the rest of the compiling process kicks in. Some preprocessor directives are simple, other much more complicated (variable arity preprocessor directives, for instance).
Of course, it requires that you have included the correct header file etc.

For this particular case, there are two parts to the answer. One part is that C preprocessor knows nothing about what function is being called, it simply does the textual replacement.
The second part is the "stringifier", #function actually replaces test as an input to PRINT with "test". Of course, it doesn't have to be a function - just because it's called printfunction, you could do:
PRINT(a+b);
and you'd get the code:
printFnctionName("a+b");
or
PRINT(a-*&1,78^%j)
and get:
printFnctionName("a-*&1,78^%j");
[Why is the u missining in printFnctionName?]
The stringification operator is very useful if you have something like
#define ASSERT(x) do { if (!x) fail_assert(#x, __FILE__, __LINE__); } while(0)
void fail_assert(const char *expr, const char *file, int line)
{
cerr << "Assertion (" << expr << ") failed at " << file << ":" << line << endl;
}
....
ASSERT(ptr != NULL);
Now you get an error message "Assertion failed (ptr != NULL) at myprog.cpp:112", which can be quite useful.

Related

Questions about C++ Preprocessor

I am learning C++ macro. And now I am totally confused. So help me! Below is my code, what I am trying to do is to use the C++ macro and call different functions using "template" such that I could only write one function and this function can be used to do the same things for different types. But when I compile this code, it throws the following errors.
testCPP.cpp: In function 'void test_int_Macro(int)':
testCPP.cpp:14: error: a function-definition is not allowed here before '{' token
testCPP.cpp:26: error: expected `}' at end of input**
#include<iostream>
#include<cstdint>
using namespace std;
#define Query_Data(Type)\
void test_##Type##_Macro(Type data){ \
cout<<"Test: "<<sizeof(data)<<" "<<endl; \
//cout<<"Type is "<<##Type##<<endl;\
}
Query_Data(int)
Query_Data(char)
int main(){
cout<<sizeof(unsigned)<<endl;
cout<<sizeof(char)<<endl;
cout<<sizeof(int32_t)<<endl;
int num=6;
char c='a';
Query_Data(num);
//Query_Data(c);
}
In C++, macros are very simple and stupid. The proeprocessor simply regurgitates whatever the macro is defined to be wherever you invoke it.
If you do the preprocessing on a piece of paper, what you come up with is:
int main(){
cout<<sizeof(unsigned)<<endl;
cout<<sizeof(char)<<endl;
cout<<sizeof(int32_t)<<endl;
int num=6;
char c='a';
void test_num_Macro(Type data){
cout<<"Test: "<<sizeof(data)<<" "<<endl;
//cout<<"Type is "<<##Type##<<endl;
}
}
The compiler gave you an error message which in this case was spot-on:
testCPP.cpp:14: error: a function-definition is not allowed here before '{' token
Look at the main function you end up with as a result of the preprocessing. It has a function declared within it. That, obviously, isn't allowed.
Now, if we follow this train of thought to the next logical stage, the question becomes "so how do I achieve what I'm trying to achineve?"
You said that:
what I am trying to do is to use the C++ macro and call different
functions using "template" such that I could only write one function
and this function can be used to do the same things for different
types.
And there is a facility in C++ for exactly this. Coincidentally, they are called templates. Here's how you might use one here:
template <typename Val>
void test ()
{
cout << "Test: " << sizeof (Val) << " " << endl;
}
int main(){
cout<<sizeof(unsigned)<<endl;
cout<<sizeof(char)<<endl;
cout<<sizeof(int32_t)<<endl;
int num=6;
char c='a';
test <char> ();
test <int> ();
}
Macros are a cludge. The are not sophisticated, they skirt around the C++ type system, they are very hard to debug and maintain. It is generally advised to avoid using them unless you have no other choice. There are places when you do have no other choice -- but this isn't one of them.
John Dibling is quite right. But I would like to point out that the easiest way to debug preprocessor issues is usually by running g++ -E src.cpp which shows you the file after it's been preprocessed. (remove your #include's first or you'll get way too much output)
And the reason for the the "expects '}' at end of input" error is that commented line in your macro. The preprocessor treats it as an empty line (without a trailing ) and so doesn't look farther and leaves your '}' out of the define.
You should avoid using the preprocessor in C++ for anything but #include and include guards in header files.
Macros are simple text replacement snippets, so you will end up defining those functions inside main function, a thing you cannot do in C++. You can see it very well if you run your code through the preprocessor:
void test_int_Macro(int data){ cout<<"Test: "<<sizeof(data)<<" "<<endl;
void test_char_Macro(char data){ cout<<"Test: "<<sizeof(data)<<" "<<endl;
int main(){
cout<<sizeof(unsigned)<<endl;
cout<<sizeof(char)<<endl;
cout<<sizeof(int32_t)<<endl;
int num=6;
char c='a';
void test_num_Macro(num data){ cout<<"Test: "<<sizeof(data)<<" "<<endl;;
}
Thus said, you should (and probably, you already got it) use templates:
template <class Type>
void Query_Data(Type data) {
std::cout << "Test: " << sizeof(data) << " " << std::endl;
}
If you wish, you can specialize the template for specific types like:
template<>
void Query_Data<int>(int data) {
std::cout << "This is an integer!" << std::endl;
}
and use them as intended:
int main(){
cout<<sizeof(unsigned)<<endl;
cout<<sizeof(char)<<endl;
cout<<sizeof(int32_t)<<endl;
int num=6;
char c='a';
Query_Data(num);
Query_Data(c);
}

What does `(...)` mean when defining a macro?

I discovered this in the source code for the Unreal Engine 4 and didn't recognize it. The specific instance of it is:
#undef UCLASS
#define UCLASS(...) \
ARadialForceActor_EVENTPARM
I'm a fairly new programmer and this kind of macro is unfamiliar to me. My guess was that it is defining a macro that will take every overloaded version of the function UCLASS (in other words, every instance of a function named UCLASS, regardless of the type and number of parameters) and replace it with the variable ARadialForceActor_EVENTPARM. Is that correct? If not, does anyone know what it means? I tried writing a code snippet to test this, but it returned error: "." may not appear in macro parameter list. I'll include it below, in case I was right about the macro, in which case I would appreciate it if someone could point out where I went wrong in my code:
#include <iostream>
#define foo( . . . ) bar
using namespace std;
int foo() {cout <<54321<<endl;}
int main()
{ bar=12345;
cout<<bar<<endl;
return 0;
}
Your guess of the meaning of #define foo(...) bar is correct. Your error is in thinking that . . . and ... are the same; they are not. ... must be written with no spaces between the dots. If I modify your program to read
#include <iostream>
#define foo(...) bar
using std::cout;
int foo()
{
cout << 54321 << '\n';
}
int main()
{
bar = 12345;
cout << bar << '\n';
return 0;
}
(please take note of other stylistic corrections; future readers of your code will thank you)
then I get error messages consistent with foo() having been replaced with bar in the function definition, as if you had written
int bar
{
cout << 54321 << '\n';
}
which is, in fact, what this tells the preprocessor to do. (The preprocessor, as always, has no understanding of the syntax of the language proper.)
#define FOO(...)
this means your macro can accept variable number of arguments. See here for details.

Can I reliably turn a string literal into a symbol name using templates (or fancy macros)?

A bit of background: I want to write a tool that compiles a bunch of named things into C++ code. The list changes and I don't want to rebuild the world when that happens. Despite that, I want to address the compiled code by (literal) name.
As an example of something that's not quite right, I could have put this in a header:
template<int name> void func();
Then my tool can generate code like:
template<> void func<1>() { ... }
template<> void func<2>() { ... }
template<> void func<3>() { ... }
Now I can call these by "name" anywhere without pre-declaring each one.
I want to do this, but with something more descriptive than integers. Ideally I want text of some form. What I need is something like:
#define FUNC_WITH_NAME(name) func_named_ ## name
That doesn't quite work, though: it needs a declaration of func_named_whatever.
The next try is no good either (and it's GCC-specific):
#define FUNC_WITH_NAME(name) ({extern void func_named_ ## name; func_named_ ## name;})
It fails because, if it's used inside a namespace, then it ends up looking for func_named_whatever in that namespace.
The best I've come up with is this:
template<char... tagchars> int tagged();
namespace NS {
int caller()
{
return tagged<'n', 'a', 'm', 'e'>();
}
}
This works, but it's ugly (and it's not obvious how to turn a string literal into a parameter pack without jumping through nasty hoops). Also, if the symbol doesn't resolve, then the error message from g++ is terrible:
In function `NS::caller()':
named_symbol.cpp:(.text+0x5): undefined reference to `int tagged<(char)110, (char)97, (char)109, (char)101>()'
collect2: error: ld returned 1 exit status
The only thing that I've come up with is a gcc extension:
extern void func_named_whatever __asm__("func_named_whatever");
But this is no good as a template argument (it only affects calls to that function; it does not affect use of magic asm-ified symbols when they're template arguments), and it defeats any link-time type checking because it turns off mangling.
Now I can call these by "name" anywhere without pre-declaring each one.
To call any function at compile time, you need to forward-declare it.
Because you want to call them at compile time, there's no need to use string literals. And you can only do this using preprocessor, not templates, because you cannot specify identifier names for templates (in C++03, at least).
Example:
#include <iostream>
#define CALL_FUNC(func, args) name_ ##func args;
void name_func1(){
std::cout << "func1" << std::endl;
}
void name_func2(int a){
std::cout << "func2:" << a << std::endl;
}
int main(int argc, char** argv){
CALL_FUNC(func1, ());
CALL_FUNC(func2, (46));
return 0;
}
You can forward-declare function within function body:
#include <iostream>
int main(int argc, char** argv){
void name_func(int);
name_func(42);
return 0;
}
void name_func(int arg){
std::cout << "func1:" << arg << std::endl;
}
So, technically, you don't even need to use preprocessor for that.
You cannot avoid forward-declaration, unless all functions arguments are known as well as their types, in which case you can hide forward-declaration with macros.
#include <iostream>
#define FUNC_NAME(func) name_ ##func
#define CALL_VOID_FUNC(func) { void FUNC_NAME(func)(); FUNC_NAME(func)(); }
int main(int argc, char** argv){
CALL_VOID_FUNC(func1);//not forward declared
return 0;
}
void name_func1(){
std::cout << "func1" << std::endl;
}
Or if you want to specify function argument types every time you call functions and know number of arguments:
#include <iostream>
#define FUNC_NAME(func) name_ ##func
#define CALL_FUNC_1ARG(func, type1, arg1) { void FUNC_NAME(func)(type1); FUNC_NAME(func)(arg1); }
int main(int argc, char** argv){
CALL_FUNC_1ARG(func1, int, 42);
return 0;
}
void name_func1(int arg){
std::cout << "func1:" << arg << std::endl;
}
Or if your function can take variable number of arguments. (parsing varargs is fun):
#include <iostream>
#define FUNC_NAME(func) name_ ##func
#define CALL_FUNC_VARIADIC(func, args) { void FUNC_NAME(func)(...); FUNC_NAME(func)args; }
int main(int argc, char** argv){
CALL_FUNC_VARIADIC(func1, (42, 43, 44));
return 0;
}
void name_func1(...){
//std::cout << "func1:" << arg << std::endl;
}
If you want to use STRINGS (as in "func1"), then you are trying to locate function at run time, not at compile time, even if you don't really think so. That's because "funcname" isn't that different from (std::string(std::string("func") + std::string("name")).c_str()) - it is pointer to memory region with character. Some compiler might provide extensions to "unstringize" string, but I'm not aware of such extensions.
In this case your only option is to write either preprocessor or code-generator, that'll scan some kind of text template (that lists functions) every time you build the project, and converts it into .h/.cpp files that are then compiled into your project. Those .h/.cpp files shoudl build function table (name to function pointer map) that is then used "behind the scenes" in your project. See Qt MOC for a working example. That'll require recompilation every time you add new function to template.
If you do not want recompilation for every new function prototype (although you can't add call to a new function without recompiling project, obviously), then your only choice is to embed scripting language into your application. This way you'll be able to add functions without recompiling. At we momen, you can embed lua, python, lisp(via ecl) and other languages. There's also working C++ interpreter, although I doubt it is embeddable.
If you do not want to use any options I listed, then (AFAIK) you cannot do that at all. Drop some requirement ("no recompilation", "no forward declaration", "call using string literal") and try again.
Can I reliably turn a string literal into a symbol name using the C macro language?
No. You can turn string literal into identifier to be processed by compiler (using stringize), but if compiler doesn't know this identifier at this point of compilation, your code won't compile. So, if you're going to call functions this way using their names, then you'll have to insure that they all were forward-declared before. And you won't be able to locate them at runtime.
C++ doesn't store names for functions and variables in compiled code. So you can't find compiled function by its name. This is because C++ linker is free to eliminate unused functions completely, inline them or create multiple copies.
What you CAN do:
Create a table of functions that you want to address by name (that maps function name to function pointer), then use this table to locate functions. You'll have to manually register every function you want to be able to find in this table. Something like this:
typedef std::string FunctionName;
typedef void(*Function)(int arg);
typedef std::map<FunctionName, Function> FunctionMap;
FunctionMap globalFunctionMap;
void callFunction(const std::string &name, int arg){
FunctionMap::iterator found = globalFunctionMap.find(name);
if (found == globalFunctionMap.end()){
//could not find function
return;
}
(*found->second)(arg);
}
Use dynamic/shared libraries. Put functions you want to be able to address into shared library (extern "C" __declspec(dllexport) or __declspec(dllexport)), mark them for export then use operating system functions to locate function within library (dlsym on linux, GetProcAddress of windows). Afaik, you might be able export functions from exe as well, so you might be able to use this approach without additional dlls.
Embed scripting language into your application. Basically, in most scripting languages you can locate and call function by its name. That'll be function declared within scripting language, obviously, not a C++ function.
Write code preprocessor that'll scan your project for "named" functions and build table of those function (method #1) somewhere automatically. Can be very difficult, because C++ is not that easy to parse.
The ideal solution would be N3413, but that's a long way off.
With thanks to 0x499602d2 and Using strings in C++ template metaprograms, here's a so-so answer:
template<char... str>
struct tag
{
template<char first>
struct prepend
{
typedef tag<first, str...> type;
};
};
template<typename Tag>
void func();
#define PREPARE_STR_TAGGER(str) \
template<int charsleft> \
struct tagger_for_##str \
{ \
typedef typename \
tagger_for_##str<charsleft-1>::type:: \
template prepend<(#str)[sizeof(#str)-1-charsleft]>::type type; \
}; \
template<> \
struct tagger_for_##str<0> \
{ \
typedef tag<> type; \
};
#define STRING_TO_TAG(str) tagger_for_##str<sizeof(#str)-1>::type
namespace SHOULD_NOT_MATTER {
PREPARE_STR_TAGGER(some_string);
void test()
{
func<STRING_TO_TAG(some_string)>();
}
}
Downsides:
It's awkward to use: you need to use PREPARE_STR_TAGGER at namespace (or maybe class) scope.
It's probably unfriendly to compile time.
The linker errors it generates are awful.
Some kind of decent hash function based on constexpr would work, but it would result in even more awful error messages.
Improvements are welcome.

Is there a way to get function name inside a C++ function?

I want to implement a function tracer, which would trace how much time a function is taking to execute. I have following class for the same:-
class FuncTracer
{
public:
FuncTracer(LPCTSTR strFuncName_in)
{
m_strFuncName[0] = _T('\0');
if( strFuncName_in ||
_T('\0') != strFuncName_in[0])
{
_tcscpy(m_strFuncName,strFuncName_in);
TCHAR strLog[MAX_PATH];
_stprintf(strLog,_T("Entering Func:- <%s>"),m_strFuncName);
LOG(strLog)
m_dwEnterTime = GetTickCount();
}
}
~FuncTracer()
{
TCHAR strLog[MAX_PATH];
_stprintf(strLog,_T("Leaving Func:- <%s>, Time inside the func <%d> ms"),m_strFuncName, GetTickCount()-m_dwEnterTime);
LOG(strLog)
}
private:
TCHAR m_strFuncName[MAX_PATH];
DWORD m_dwEnterTime;
};
void TestClass::TestFunction()
{
// I want to avoid writing the function name maually..
// Is there any macro (__LINE__)or some other way to
// get the function name inside a function ??
FuncTracer(_T("TestClass::TestFunction"));
/*
* Rest of the function code.
*/
}
I want to know if there is any way to get the name of the function from inside of a function? Basically I want the users of my class to simply create an object the same. They may not pass the function name.
C99 has __func__, but for C++ this will be compiler specific. On the plus side, some of the compiler-specific versions provide additional type information, which is particularly nice when you're tracing inside a templatized function/class.
MSVC: __FUNCTION__, __FUNCDNAME__, __FUNCSIG__
GCC: __func__, __FUNCTION__, __PRETTY_FUNCTION__
Boost library has defined macro BOOST_CURRENT_FUNCTION for most C++ compilers in header boost/current_function.hpp. If the compiler is too old to support this, the result will be "(unknown)".
VC++ has
__FUNCTION__ for undecorated names
and
__FUNCDNAME__ for decorated names
And you can write a macro that will itself allocate an object and pass the name-yelding macro inside the constructor. Smth like
#define ALLOC_LOGGER FuncTracer ____tracer( __FUNCTION__ );
C++20 std::source_location::function_name
main.cpp
#include <iostream>
#include <string_view>
#include <source_location>
void log(std::string_view message,
const std::source_location& location = std::source_location::current()
) {
std::cout << "info:"
<< location.file_name() << ":"
<< location.line() << ":"
<< location.function_name() << " "
<< message << '\n';
}
int f(int i) {
log("Hello world!"); // Line 16
return i + 1;
}
int f(double i) {
log("Hello world!"); // Line 21
return i + 1.0;
}
int main() {
f(1);
f(1.0);
}
Compile and run:
g++ -ggdb3 -O0 -std=c++20 -Wall -Wextra -pedantic -o source_location.out source_location.cpp
./source_location.out
Output:
info:source_location.cpp:16:int f(int) Hello world!
info:source_location.cpp:21:int f(double) Hello world!
so note how the call preserves caller information, so we see the desired main call location instead of log.
I have covered the relevant standards in a bit more detail at: What's the difference between __PRETTY_FUNCTION__, __FUNCTION__, __func__?
Tested on Ubuntu 22.04, GCC 11.3.
I was going to say I didn't know of any such thing but then I saw the other answers...
It might interest you to know that an execution profiler (like gprof) does exactly what you're asking about - it tracks the amount of time spent executing each function. A profiler basically works by recording the instruction pointer (IP), the address of the currently executing instruction, every 10ms or so. After the program is done running, you invoke a postprocessor that examines the list of IPs and the program, and converts those addresses into function names. So I'd suggest just using the instruction pointer, rather than the function name, both because it's easier to code and because it's more efficient to work with a single number than with a string.

How to find the name of the current function at runtime?

After years of using the big ugly MFC ASSERT macro, I have finally decided to ditch it and create the ultimate ASSERT macro.
I am fine with getting the file and line number, and even the expression that failed. I can display a messagebox with these in, and Abort/Retry/Cancel buttons.
And when I press Retry the VS debugger jumps to the line containing the ASSERT call (as opposed to the disassembly somewhere like some other ASSERT functions). So it's all pretty much working.
But what would be really cool would be to display the name of the function that failed.
Then I can decide whether to debug it without trying to guess what function it's in from the filename.
e.g. if I have the following function:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
ASSERT(lpCreateStruct->cx > 0);
...
}
Then when the ASSERT fires, the messagebox would show something like:
Function = CMainFrame::OnCreate
So, what's the simplest way of finding out the current function name, at runtime?
It should not use MFC or the .NET framework, even though I do use both of these.
It should be as portable as possible.
Your macro can contain the __FUNCTION__ macro.
Make no mistake, the function name will be inserted into the expanded code at compile time, but it will be the correct function name for each call to your macro. So it "seems like" it happens in run-time ;)
e.g.
#define THROW_IF(val) if (val) throw "error in " __FUNCTION__
int foo()
{
int a = 0;
THROW_IF(a > 0); // will throw "error in foo()"
}
The C++ preprocessor macro __FUNCTION__ gives the name of the function.
Note that if you use this, it's not really getting the filename, line number, or function name at runtime. Macros are expanded by the preprocessor, and compiled in.
Example program:
#include <iostream>
void function1()
{
std::cout << "my function name is: " << __FUNCTION__ << "\n";
}
int main()
{
std::cout << "my function name is: " << __FUNCTION__ << "\n";
function1();
return 0;
}
output:
my function name is: main
my function name is: function1
There's no standard solution. However, BOOST_CURRENT_FUNCTION is portable for all practical purposes. The header does not not depend on any of the other Boost headers, so can be used standalone if the overhead of the whole library is unacceptable.
__FUNCTION__ or __FUNC__ or __PRETTY_FUNCTION__
http://msdn.microsoft.com/en-us/library/b0084kay(VS.80).aspx
http://gcc.gnu.org/onlinedocs/gcc/Function-Names.html
In GCC you can use the __PRETTY_FUNCTION__ macro.
Microsoft also have an equivalent __func__ macro although I don't have that available to try.
e.g. to use __PRETTY_FUNCTION__ putting something like this at the beginning of your functions and you'll get a complete trace
void foo(char* bar){
cout << __PRETTY_FUNCTION__ << std::endl
}
which will output
void foo(char* bar)
You also have the __FILE__ and __LINE__ macros available under all standard c/c++ compilers if you want to output even more information.
In practice I have a special debugging class which I use instead of cout. By defining appropriate environment variables I can get a full program trace. You could do something similar. These macros are incredibly handy and it's really great to be able to turn on selective debugging like this in the field.
EDIT: apparently __func__ is part of the standard? didn't know that. Unfortunately, it only gives the function name and not the parameters as well. I do like gcc's __PRETTY_FUNC__ but it's not portable to other compilers.
GCC also supports __FUNCTION__.
You can use the __FUNCTION__ macro which at compile time will be expanded to the name of the function.
Here's an example of how to use it in an assert macro.
#define ASSERT(cond) \
do { if (!(cond)) \
MessageBoxFunction("Failed: %s in Function %s", #cond, __FUNCTION__);\
} while(0)
void MessageBoxFunction(const char* const msg, ...)
{
char szAssertMsg[2048];
// format args
va_list vargs;
va_start(vargs, msg);
vsprintf(szAssertMsg, msg, vargs);
va_end(vargs);
::MessageBoxA(NULL, szAssertMsg, "Failed Assertion", MB_ICONERROR | MB_OK);
}
C++20 std::source_location::function_name
No macros are needed now that we have proper standardization:
main.cpp
#include <iostream>
#include <string_view>
#include <source_location>
void log(std::string_view message,
const std::source_location& location = std::source_location::current()
) {
std::cout << "info:"
<< location.file_name() << ":"
<< location.line() << ":"
<< location.function_name() << " "
<< message << '\n';
}
int f(int i) {
log("Hello world!"); // Line 16
return i + 1;
}
int f(double i) {
log("Hello world!"); // Line 21
return i + 1.0;
}
int main() {
f(1);
f(1.0);
}
Compile and run:
g++ -ggdb3 -O0 -std=c++20 -Wall -Wextra -pedantic -o source_location.out source_location.cpp
./source_location.out
Output:
info:source_location.cpp:16:int f(int) Hello world!
info:source_location.cpp:21:int f(double) Hello world!
so note how the call preserves caller information, so we see the desired main call location instead of log.
I have covered the relevant standards in a bit more detail at: What's the difference between __PRETTY_FUNCTION__, __FUNCTION__, __func__?
Tested on Ubuntu 22.04, GCC 11.3.
you can easily use func.
it will take back you current function name at runtime which raised the exception.
usage:
cout << __func__ << ": " << e.what();