11
\$\begingroup\$
#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?.

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Oct 12, 2014 at 16:20
\$\endgroup\$
6
  • \$\begingroup\$ You could use some preprocessor #define like with assert, if you like that more. \$\endgroup\$ Commented Oct 12, 2014 at 16:41
  • \$\begingroup\$ I can't find a meaning for your class, sorry. A debugger just works better. \$\endgroup\$ Commented Oct 12, 2014 at 17:23
  • 3
    \$\begingroup\$ @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. \$\endgroup\$ Commented Oct 12, 2014 at 17:31
  • \$\begingroup\$ @LokiAstari I'm looking for explainations which do help for a code review. Also, your example is questionably related. \$\endgroup\$ Commented Oct 12, 2014 at 17:45
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ Commented Oct 21, 2014 at 5:05

4 Answers 4

10
\$\begingroup\$

Stop doing this:

using namespace std;

see: Why is "using namespace std;" considered bad practice?

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;
}
answered Oct 12, 2014 at 17:36
\$\endgroup\$
2
\$\begingroup\$

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();
 }
community wiki

\$\endgroup\$
1
\$\begingroup\$

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.

answered Oct 14, 2014 at 7:20
\$\endgroup\$
1
\$\begingroup\$

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.

answered Feb 26, 2016 at 10:34
\$\endgroup\$
2
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Feb 26, 2016 at 11:04
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Feb 26, 2016 at 11:08

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.