# Generic logging class for tracing the function calls

#include<iostream>
#include<string>
using namespace std;

// Generic class for tracing the function call
class functionlogging {
private:
string name;
string in{ ">>" };
string out{ "<<" };
public:
functionlogging(string x) :name(x) {
cout << in << name << endl;
}
~functionlogging(){
cout << out << name << endl;
}
};

//uses
void generic_function() {
functionlogging logger{ __func__ };
int a = 10;
int b = 100;
a += b;
}

int main() {
generic_function();
}


Many times, we do need to log when function call starts and ends for better understanding. With modern C++ concepts like __funct__/RAII, I wrote the small class which can be used to achieve trace. With this I was able to achieve this for above "generic_function()".

# Output

>>generic_function
<<generic_function


I wanted others opinion about the functionlogging class and how to make it in such a way that user of this class would have to do the minimal work/code changes in his/her code base.

At present user of this class needs to create a object of this class and pass the __func__ information. Is it acceptable or in a way can it be embed inside something by which user of the class almost do not require to do anything?.

• You could use some preprocessor #define like with assert, if you like that more.
– user52292
Oct 12, 2014 at 16:41
• I can't find a meaning for your class, sorry. A debugger just works better.
– edmz
Oct 12, 2014 at 17:23
• @black. That is neither true nor a useful statement. In a data driven program the call history will not be obvious and thus logging is needed to trace where the code has been before a crash point (a lot of that stack information may no longer be available in the core file). Also the comment does not help in any way review the code. Oct 12, 2014 at 17:31
• @LokiAstari I'm looking for explainations which do help for a code review. Also, your example is questionably related.
– edmz
Oct 12, 2014 at 17:45
• If you don't want to post a new question to get further feedback, you can always post your updated code as an answer to help future readers. That's #3 in Jamal's link, and it seems to fit your stated goal best. Oct 21, 2014 at 5:05

Stop doing this:

using namespace std;


These two are not unique to the class.

string in{ ">>" };
string out{ "<<" };


May as well make them static. Also they re never modified so make them const.

No need to force a flush with std::endl

    cout << in << name << endl;


Prefer "\n" when you don't need a flush (also cerr or clog may be better choices of output stream).

That seems like an overly verbose and error prone way of use.

void generic_function() {
functionlogging logger{ __func__ };


You have to use up a variable and remember __func__. Can't we get a macro in here to do all the for you? I actually need to look up to see if func is a standard macro.

Just checked the standard:

8.4.1 In general
Paragrah 8:
The function-local predefined variable __func__ is defined as if a definition of the form

static const char __func__[] = "function-name ";


So I would define the macros:

#define LOG_ENTRY_EXIT_FOR(x)       functionlogging  SomeLongNameThatIsNotLikelyToBeUsedInTheFunctionlogger(x)
#define LOG_ENTRY_EXIT              LOG_ENTRY_EXIT_FOR(__func__)


Then usage is simply:

void generic_function() {
LOG_ENTRY_EXIT;

int a = 10;
int b = 100;
a += b;
}


Just a minor addition. Storing (and passing) the function name in a const char* will eliminate the costly (dynamic memory allocation) construction of a string.

The below is updated code after incorporating the suggestion in this post. This is just for easy reference for future reader.

  #include<iostream>
#include<string>

// Generic class for tracing the function call
class functionlogging {
private:
std::string name;
static std::string in;
static std::string out;
public:
functionlogging(std::string x) :name(x) {
std::cout << in << name <<"\n";
}
~functionlogging(){
std::cout << out << name <<"\n";
}
};

std::string functionlogging::in{ ">>" };
std::string functionlogging::out{ "<<" };

//Define MACRO for easy use for end user.
#define LOG_ENTRY_EXIT_FOR(x)       functionlogging  SomeLongNameThatIsNotLikelyToBeUsedInTheFunctionlogger(x)
#define LOG_ENTRY_EXIT              LOG_ENTRY_EXIT_FOR(__func__)

//uses
void generic_function() {
LOG_ENTRY_EXIT;
int a = 10;
int b = 100;
a += b;
}

int main() {
generic_function();
}


Sounds great. I would recommend a little improvement to Loki Astari's answer.

By changing the way you define LOG_ENTRY_EXIT,

#if defined(DEBUG)
#define LOG_ENTRY_EXIT   LOG_ENTRY_EXIT_FOR(__func__)
#else
#define LOG_ENTRY_EXIT
#endif


One will be able to compile it in or out for say release build if needed.

We use this type of tracing quite a lot in game development code.

• If you're posting a comment to someone else's answer, but find it noteworthy enough to post as an answer, be sure to point out what answer you're referencing to. Feb 26, 2016 at 11:04
• I've edited your answer as an example; like this it's clearer where your contribution is coming from. When you get more reputation (50+), you'll be able to comment on other people's posts, after which you may want to write answers like this as comments instead. Feb 26, 2016 at 11:08