My application uses another output than the standard output for logging information, which is why I wrote my own Log(), Error(), Panic() and Assert() functions. To organize things nicely, I enclose all the debugging stuff in a Debug namespace.
It would make more sense for the Assert() function to also provide a source file and line number, which is only possible using the __LINE__ and __FILE__ macros. However, it is pretty unpleasant, inefficient etc... to always have to specify these two parameters.
So this is how my code would look like:
namespace Debug {
void Assert (int condition, std::string message, std::string file, int line);
}
My question is, is it possible to place a macro which includes those two parameters inside the Debug namespace? Like this:
namespace Debug {
void Assert_ (int condition, std::string message, std::string file, int line);
#define Assert(a,b) Assert_(a, b, __FILE__, __LINE__)
}
// .... Somewhere where I call the function ....
Debug::Assert (some_condition, "Some_condition should be true");
// Output: Assertion failed on line 10 in file test.cpp:
// Some_condition should be true
Is this valid c++? If not, is there any way of making this work?
#define is a preprocessor directive. The macros are being replaced before anything else apart from removing comments (which means, before compilation). So at the time macros are replaced, the compiler knows nothing about your namespaces.
As other people state, in your case it will be fine. However, This is how you can get problems:
namespace A
{
void Assert_ (int condition, std::string message, std::string file, int line)
{
std::cout << "A";
}
#define Assert(a,b) Assert_(a, b, __FILE__, __LINE__)
}
namespace B
{
void Assert_ (int condition)
{
std::cout << "B";
}
#define Assert(a,b) Assert_(a)
}
int main(int argc, char *argv[])
{
A::Assert(0,"asdasd");
B::Assert(0,"asdasd");
}
So while it looks like the defines are "in the namespaces", they are not, and the last #define will be always be used, which in this case will lead to a compile-time error, because the code in main will be replaced by:
A::Assert(0);
B::Assert(0);
instead of
A::Assert(0,"asdasd", _FILE_, _LINE_);
B::Assert(0);
No, the preprocessor doesn't care about namespaces at all. In fact, the preprocessor runs, at least conceptually, before the compiler sees anything.
For myself, I just do a standard ASSERT macro, and expect that no "sane namespace" has something called ASSERT. Problem solved. Should I require a library that has an ASSERT of its own then I can still decide how to deal with this; however, the only library that I'm currently using with its own "assert" calls it BOOST_ASSERT or something like that...
namespace Debug
{
void Assert_(int condition, std::string message, std::string file, int line);
#define Assert(a,b) Assert_(a, b, __FILE__, __LINE__)
}
// .... Somewhere where I call the function ....
Debug::Assert (some_condition, "Some_condition should be true");
This specific usage would do exactly what you want, but the Assert macro is in no way part of the Debug namespace... it's exactly as if you'd done:
namespace Debug
{
void Assert_(int condition, std::string message, std::string file, int line);
}
#define Assert(a,b) Assert_(a, b, __FILE__, __LINE__)
// .... Somewhere where I call the function ....
Debug::Assert (some_condition, "Some_condition should be true");
Here, the substitution works not because Assert was in the Debug namespace (it's not in your code or this code, and the preprocessor has no clue what namespaces are about) - it works because Assert is recognised as an identifier for a macro, the substitution of Assert_ is made, then later the compiler proper happens to find there's a Debug::Assert_
So, say you have somewhere later in your translation unit you have some completely unrelated code:
my_object.Assert(my_functor);
The macro substituion will still kick in to produce a compile-time error saying you have the wrong number of arguments to a macro. Say the unrelated code was instead:
my_object.Assert(my_functor, "some text");
Then that would be replaced with:
my_object.Assert_(my_functor, "some text", __FILE__, __LINE__);
(Separately, it's standard practice not to use lower case letters in preprocessor macro names).
You can try __PRETTY_FUNCTION __ macro to print all the namespaces including function arguments.
Yes, and your macro would expand to exactly what you expect.
Debug::Assert (some_condition, "Some_condition should be true");
would be replaced by
Debug::Assert_(some_condition, "Some_condition should be true", __FILE__, __LINE__)
Related
If there is a function like the following,
void logData(std::string data, int line=__LINE__);
is the default parameter evaluated where the function is called, or where it is declared? Is the behavior standard, or does it depend on the compiler?
You asked:
is the default parameter evaluated where the function is called, or where it is declared? Is the behavior standard, or does it depend on the compiler?
The value of the default parameter will be the line number of the file where the function is declared. That is as per the standard.
From the C++11 Standard:
16.8 Predefined macro names
...
_ _ LINE _ _
The presumed line number (within the current source file) of the current source line (an integer constant).
Since __LINE__ is a pre-processor macro, the code being compiled by the compiler does not have __LINE__ in it. In its place, it will see an integer constant that represents the line number of the line in the file, which is the file where the function is declared.
This sounds like a question a Python programmer might ask but you've picked a variant that has two answers.
The first part is __LINE__ which is a pre-processor macro. Pre-processing is, as the name suggests, done before some "processing" step. In this case, it happens before the compiler tries to compile the code. pre-processing involves replacing "#include" statements with the pre-processed contents of the file, evaluating and replacing macros, #define and #if statements etc.
So when the compiler sees
void logData(... __LINE__)
on line 123 of a file, the __LINE__ is replaced with the constants 123. You can avoid this by using macros, e.g.
enum Level { DEBUG, NOTE, WARNING, ERROR };
#define FLD __FILE__, __LINE__, DEBUG
#define FLN __FILE__, __LINE__, NOTE
#define FLW __FILE__, __LINE__, WARNING
#define FLE __FILE__, __LINE__, ERROR
void log(const char* file_, size_t line_, Level level_, const char* what);
...
logData(FLD, "debug message");
As to where the arguments are "evaluated", call site; so you will not run into Python's
from __future__ import print_function
def f(inlist, l=[]):
if l:
l.append("unexpected surprise")
l.extend(inlist)
return l
f([1])
print(f([2]))
http://ideone.com/GvmsL6
[1, 'unexpected surprise', 2]
in c++
#include <iostream>
#include <vector>
#include <string>
using strvec = std::vector<std::string>;
strvec f(strvec in, strvec out={})
{
if (!out.empty())
out.push_back("unexpected surprise");
out.insert(out.end(), in.cbegin(), in.cend());
return out;
}
int main()
{
f({"a"});
auto vec = f({"b"});
for (auto& str: vec) {
std::cout << str << "\n";
}
}
See http://ideone.com/17ilNL
My application uses another output than the standard output for logging information, which is why I wrote my own Log(), Error(), Panic() and Assert() functions. To organize things nicely, I enclose all the debugging stuff in a Debug namespace.
It would make more sense for the Assert() function to also provide a source file and line number, which is only possible using the __LINE__ and __FILE__ macros. However, it is pretty unpleasant, inefficient etc... to always have to specify these two parameters.
So this is how my code would look like:
namespace Debug {
void Assert (int condition, std::string message, std::string file, int line);
}
My question is, is it possible to place a macro which includes those two parameters inside the Debug namespace? Like this:
namespace Debug {
void Assert_ (int condition, std::string message, std::string file, int line);
#define Assert(a,b) Assert_(a, b, __FILE__, __LINE__)
}
// .... Somewhere where I call the function ....
Debug::Assert (some_condition, "Some_condition should be true");
// Output: Assertion failed on line 10 in file test.cpp:
// Some_condition should be true
Is this valid c++? If not, is there any way of making this work?
#define is a preprocessor directive. The macros are being replaced before anything else apart from removing comments (which means, before compilation). So at the time macros are replaced, the compiler knows nothing about your namespaces.
As other people state, in your case it will be fine. However, This is how you can get problems:
namespace A
{
void Assert_ (int condition, std::string message, std::string file, int line)
{
std::cout << "A";
}
#define Assert(a,b) Assert_(a, b, __FILE__, __LINE__)
}
namespace B
{
void Assert_ (int condition)
{
std::cout << "B";
}
#define Assert(a,b) Assert_(a)
}
int main(int argc, char *argv[])
{
A::Assert(0,"asdasd");
B::Assert(0,"asdasd");
}
So while it looks like the defines are "in the namespaces", they are not, and the last #define will be always be used, which in this case will lead to a compile-time error, because the code in main will be replaced by:
A::Assert(0);
B::Assert(0);
instead of
A::Assert(0,"asdasd", _FILE_, _LINE_);
B::Assert(0);
No, the preprocessor doesn't care about namespaces at all. In fact, the preprocessor runs, at least conceptually, before the compiler sees anything.
For myself, I just do a standard ASSERT macro, and expect that no "sane namespace" has something called ASSERT. Problem solved. Should I require a library that has an ASSERT of its own then I can still decide how to deal with this; however, the only library that I'm currently using with its own "assert" calls it BOOST_ASSERT or something like that...
namespace Debug
{
void Assert_(int condition, std::string message, std::string file, int line);
#define Assert(a,b) Assert_(a, b, __FILE__, __LINE__)
}
// .... Somewhere where I call the function ....
Debug::Assert (some_condition, "Some_condition should be true");
This specific usage would do exactly what you want, but the Assert macro is in no way part of the Debug namespace... it's exactly as if you'd done:
namespace Debug
{
void Assert_(int condition, std::string message, std::string file, int line);
}
#define Assert(a,b) Assert_(a, b, __FILE__, __LINE__)
// .... Somewhere where I call the function ....
Debug::Assert (some_condition, "Some_condition should be true");
Here, the substitution works not because Assert was in the Debug namespace (it's not in your code or this code, and the preprocessor has no clue what namespaces are about) - it works because Assert is recognised as an identifier for a macro, the substitution of Assert_ is made, then later the compiler proper happens to find there's a Debug::Assert_
So, say you have somewhere later in your translation unit you have some completely unrelated code:
my_object.Assert(my_functor);
The macro substituion will still kick in to produce a compile-time error saying you have the wrong number of arguments to a macro. Say the unrelated code was instead:
my_object.Assert(my_functor, "some text");
Then that would be replaced with:
my_object.Assert_(my_functor, "some text", __FILE__, __LINE__);
(Separately, it's standard practice not to use lower case letters in preprocessor macro names).
You can try __PRETTY_FUNCTION __ macro to print all the namespaces including function arguments.
Yes, and your macro would expand to exactly what you expect.
Debug::Assert (some_condition, "Some_condition should be true");
would be replaced by
Debug::Assert_(some_condition, "Some_condition should be true", __FILE__, __LINE__)
I am working on a c++ unit tester(mostly as practice) and had some questions about my implementation.
I wanted to have the ability to overload my custom assertions so I decided to implement them as functions that I wrapped in a namespace.
My current implementation is as follows:
Tester.h
#include <string>
#define INFO __FILE__, __LINE__
namespace Tester
{
void Assert(char const* input, char const* file_path, int line_number, std::string error_message);
...more overloaded Asserts and some Log functions...
}
And when I call the function:
#include "Tester.h"
...code...
Tester::Assert(false, INFO, "Some message");
...code...
This works but I´m not sure that the 'INFO' macro is good practice.
I welcome all suggestions and pointers about this implementation, and feel free to tell me if it makes no sense and I should be doing something completely different ;)
INFO as a macro seems perfectly fine. An alternative, which I prefer is to have a macro
#define TEST_ASSERT(condition, message) Tester::Asssert(condition, __FILE__, __LINE__, message)
or something of that sort.
If you have different number of arguments, something like this may work:
#define TEST_ASSERT(condition, ...) Tester::Asssert(condition, __FILE__, __LINE__, __VA_ARGS__)
Assuming your compiler is new enough, that is.
I am trying to write a wrapper function to figure out who is calling a specific function. So in .h file I added the following: (and implementation in the .cc file)
extern int foo(/*some arguments*/);
extern void call_log(const char*file,const char*function,const int line,const char*args);
#define foo(...) (call_log(__FILE__, __FUNCTION__, __LINE__, "" #__VA_ARGS__), foo(__VA_ARGS__))
However, I get the following error:
error: expected a type specifier
(call_log(__FILE__, __FUNCTION__, __LINE__, "" #__VA_ARGS__),foo(__VA_ARGS__)
Assume that the foo function is called with some parameters and returns an int.
the compiler is gcc 3.4
Thanks
EDIT
removed "." and extra spaced, yet problem still there. Can anyone see what can cause it. Also notice that I am using variadic macros -- supported by my compiler (c99)
Edit 2
Just to get the claims about my illegal use of some c/c++ constructs. The following code below works, and I am trying to adapt it to my current (above function)
#include <stdio.h>
int funcA( int a, int b ){ return a+b; }
// instrumentation
void call_log(const char*file,const char*function,const int line,const char*args){
printf("file:%s line: %i function: %s args: %s\n",file,line,function,args);
}
#define funcA(...) \
(call_log(__FILE__, __FUNCTION__, __LINE__, "" #__VA_ARGS__), funcA(__VA_ARGS__))
// testing
void funcB()
{
funcA(7,8);
}
int main(void){
int x = funcA(1,2)+
funcA(3,4);
printf( "x: %i (==10)\n", x );
funcA(5,6);
funcB();
}
Edit 3
As litb pointed out, the problem is, in fact, due to macro substitutions. I also noticed that foo is not only a function call but also used as ptr->foo[] in some cases. Any ides how to resolve this sort of issues, without breaking more code
The best way to find out what's wrong would be to make the compiler show the preprocessed code. You can then easier spot the problem in the offending line.
If I'm not mistaken I believe you have a number of syntax errors in the definition and declaration of call_log.
In the definition I am pretty sure you need a space between the const char* and the variable name. ie...
extern void call_log(const char* file,const char* function,const int line,const char* args);
In addition, in the declaration, I don't think you can append #__VA_ARGS__ to "" in the manner you are doing. The macro will resolved this as:
(call_log(file_name, function_name, line_#, "" arg1, arg2...), foo(args[])
which is not a valid function call. On a side-note you are also missing a semicolon after the macro definition.
Finally, I do not see a reference to foo(args) in your macro definition; It's possible I'm missing some context but you may wish to look at that as well.
Hope this helps...
CJ
Is it possible to do something like this
#ifdef SOMETHING
#define foo //
#else
#define foo MyFunction
#endif
The idea is that if SOMETHING is defined, then calls to foo(...) become comments (or something that doesn't get evaluated or compiled), otherwise it becomes a call to MyFunction.
I've seen __noop used, but I don't believe I can use that.
EDIT(s):
I don't think I can really use a macro here, because MyFunction takes a variable number of arguments.
Also, I'd like to make it so the arguments are NOT evaluated! (So doing something like commenting out the body of MyFunction doesn't really give me what I need, as the arguments will still be evaluated)
Try this:
#ifdef SOMETHING
#define foo(x)
#else
#define foo(x) MyFunction(x)
#endif
If your function has several arguments, then:
#ifdef SOMETHING
#define foo(x,y,z)
#else
#define foo(x,y,z) MyFunction(x,y,z)
#endif
If your function has a variable number of arguments, then your compiler may support so-called "variadic macros", like this:
#ifdef SOMETHING
#define foo(...)
#else
#define foo(...) MyFunction(__VA_ARGS__)
#endif
The reason which I've seen this kind of thing used in practice is to get rid of logging functions from a release build. However, see also Separate 'debug' and 'release' builds? in which people question whether you should even have different builds.
Alternatively, instead of redefining the function call as nothing, Jonathan's comment to this answer suggested doing something like the following:
#ifdef SOMETHING
#define foo(...) do { if (false) MyFunction(__VA_ARGS__) } while (0)
#else
#define foo(...) do { if (true) MyFunction(__VA_ARGS__) } while (0)
#endif
The reasoning for doing this is so that the function call is always compiled (so it won't be left with gratuitous errors like references to deleted variables), but only called when needed: see Kernighan & Pike The Practice of Programming and also the Goddard Space Flight Center programming standards.
From a debug.h file (originating from 1990, and therefore not using __VA_ARGS__):
/*
** Usage: TRACE((level, fmt, ...))
** "level" is the debugging level which must be operational for the output
** to appear. "fmt" is a printf format string. "..." is whatever extra
** arguments fmt requires (possibly nothing).
** The non-debug macro means that the code is validated but never called.
** -- See chapter 8 of 'The Practice of Programming', by Kernighan and Pike.
*/
#ifdef DEBUG
#define TRACE(x) db_print x
#else
#define TRACE(x) do { if (0) db_print x; } while (0)
#endif /* DEBUG */
With C99, there's no longer a need for the double parentheses trick. New code should not use it unless C89 compatibility is an issue.
Maybe an easier way to do this would be to conditionally omit the body of the function?
void MyFunction() {
#ifndef SOMETHING
<body of function>
#endif
}
Unless you specifically don't want a function call to be made at all, this seems like a clean way to achieve your goal.
Unfortunately the current C++ version doesn't support variadic macros.
However, you can do this:
#ifdef SOMETHING
#define foo
#else
#define foo(args) MyFunction args
#endif
// you call it with double parens:
foo((a, b, c));
If, in the case you don't want foo called, you define it as:
void foo() {}
any calls to foo() should be optimized way.
What about something along these lines:
#ifdef NDEBUG
#define DEBUG(STATEMENT) ((void)0)
#else
#define DEBUG(STATEMENT) (STATEMENT)
#endif
You would use it like this to log debugging messages:
DEBUG(puts("compile with -DNDEBUG and I'm gone"));
A non-generic version for formatted output with additional debugging information using C99 variadic macros and the __func__ identifier could look like this:
#ifdef NDEBUG
#define Dprintf(FORMAT, ...) ((void)0)
#define Dputs(MSG) ((void)0)
#else
#define Dprintf(FORMAT, ...) \
fprintf(stderr, "%s() in %s, line %i: " FORMAT "\n", \
__func__, __FILE__, __LINE__, __VA_ARGS__)
#define Dputs(MSG) Dprintf("%s", MSG)
#endif
Here's how you'd use these macros:
Dprintf("count = %i", count);
Dputs("checkpoint passed");
Likely, you don't want to do the simple "code removal" as suggested,
because your callers will be expecting the side effects of the
arguments to happen. Here are some troublesome caller snippets that
should get you thinking:
// pre/post increment inside method call:
MyFunction(i++);
// Function call (with side effects) used as method argument:
MyFunction( StoreNewUsernameIntoDatabase(username) );
If you were to disable MyFunction by simply saying:
#define MyFunction(x)
then the side effects that the callers were expecting would go away,
and their code would break, and be quite difficult to debug. I like
the "sizeof" suggestion above, and I also like the suggestion to just
disable the body of MyFunction() via #ifdef's, although that means
that all callers get the same version of MyFunction(). From your
problem statement, I presume that's not actually what you want.
If you really need to disable MyFunction() via preprocessor defines on
a per-source-file basis, then I'd do it like this:
#ifdef SOMETHING
#define MyFunction(x) NoOp_MyFunction(x)
int NoOp_MyFunction(x) { }
#endif
You could even include the implementation of NoOp_MyFunction() inside
the source & headers for MyFunction(). You also have the flexibility
to add extra logging or debugging information in NoOp_MyFunction() as
well.
No, the C and C++ Standards say you cannot #define something to be a comment, so
#define foo //
won't work.
#ifdef SOMETHING
#define foo sizeof
#else
#define foo MyFunction
#endif
I'm assuming that foo is a printf style function? Anyways, this won't work with a zero parameter function, but if that were the case, you would already know what to do. If you really want to be anal you can use (void)sizeof but that's probably unnecessary.
I'm a little reluctant to post this answer because it's use of macro hackery can become the source of problems. However - if the calls to the function you want to have disappear are always used alone in a statement (ie., they are never part of a larger expression), then something like the following could work (and it handles varargs):
#ifdef SOMETHING
#define foo (1) ? ((void) 0) : (void)
#else
#define foo MyFunction
#endif
So if you have the line of code:
foo( "this is a %s - a++ is %d\n", "test", a++);
it will end up after the preprocessing step as either:
MyFunction( "this is a %s - a++ is %d\n", "test", a++);
or
(1) ? ((void) 0) : (void)( "this is a %s - a++ is %d\n", "test", a++);
which turns the pseudo-function's parameter list into a bunch of expressions separated by the comma operator that will never be evaluated, since the conditional always returns the ((void) 0) result.
A variant of this is something close to what ChriSW and Jonathan Leffler suggested:
#ifdef SOMETHING
#define foo if (0) MyFunction
#else
#define foo if (1) MyFunction
#endif
This is slightly different in that it does not require the compiler to support variadic macros (__VA_ARGS__).
I think this can be useful for eliminating debug trace function calls which are generally never combined into a larger expression, but beyond that I think it's a dangerous technique.
Note the potential for problems - especially if the parameters in the call produce side-effects (this is a general problem with macros - not just this hack). In the example, the a++ will be evaluated only if SOMETHING is defined in the build, otherwise it's not. So if code after the call depends on the value of a to be incremented, one of the builds has a bug.
If I remember correctly, you should be able to #define your macro to "nothing" and that will cause the compiler to ignore that call
#define foo()
foo(); // this will be ignored
What about surrounding each call to myFunction with
#ifdef SOMETHING
myFunction(...);
#endif
?