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
Related
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__)
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 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
I am trying to figure out how people use the __LINE__ macro at work. How do you guys use it?
You can use __LINE__, along with __FILE__, to report where problems occur in the source code.
Consider, for example, the assert() macro - this wording from the C99 standard, but C++ is similar, except it does not mention __func__:
When it is executed, if expression (which shall have a scalar type) is false (that is,
compares equal to 0), the assert macro writes information about the particular call that
failed (including the text of the argument, the name of the source file, the source line
number, and the name of the enclosing function — the latter are respectively the values of
the preprocessing macros __FILE__ and __LINE__ and of the identifier
__func__) on the standard error stream in an implementation-defined format.
#define assert(x) (void)(((x)==0)?_Assert(#x,__FILE__,__LINE__,__func__):0)
An even simpler example, here's a macro I occasionally use when all other forms of debugging have failed:
#define GOT_HERE std::cout << "At " __FILE__ ":" << __LINE__ << std::endl
Then when your code is mysteriously crashing and taking the device down with it, you can at least sprinkle this macro liberally into the source, in the hope that it will let you narrow down where the crash occurs (and after how many repeats). In practice you might not write to std::cout, but rather use the lowest-level, most reliable character output available on the platform.
I wrote a wrapper for malloc:
#if DEBUG
#define malloc(s) debugging_malloc(s, __FILE__, __LINE__)
#define free(p) debugging_free(p)
// Also, calloc(), strdup(), realloc() should be wrapped.
#endif // DEBUG
Within the wrapper, allocations are tracked according to the file and line number at which they occur. When the program exits, a utility functions outputs a list of any unfreed blocks.
If you are using gcc, it also gives you __FUNCTION__, which is really nice. C99-compliant compilers also have __func__, just as handy.
Most of the answers so far have involved some sort of debugging code. Another use of __LINE__ (and possibly __FILE__) is to enable a macro to generate a unique identifier each time it's called. This implementation of coroutines in C uses these macros to generate labels for a case statement, so it can jump to the last line you called yield from.
Just like this:
$ cat line.cc
#include <iostream>
int main(void) {
std::cout << "Hello, world from " << __LINE__ << std::endl;
return 0;
}
$ g++ -o line line.cc
$ ./line
Hello, world from 4
$
if (something truly impossible has happened) {
fprintf(stderr, "Value of PI less than 3 detected at %s line %d\n", __FILE__, __LINE__);
}
It's especially handy in CPP macros that detect intolerable conditions.
It's really just for debugging/logging purposes. I rarely use it because I tend to rely on debuggers like gdb more often.
But you could always use it when outputting debug information.
void dosomething(Object* o)
{
if (!o) {
std::cerr << __FILE__ << ":" << __LINE__ << ": o is NULL!\n";
abort();
}
}
Just to vaguely quote from the top of my head:
#define assert(e) ((e) ? (void)0 : printf("Assertion failed %s, %s : %s", #e, __FILE__, __LINE__))
what I'd like to do (for logging purposes) is something like this:
This code has been written to show my problem, actual code is complex and yes, I have good reasons to use macros even on C++ =)
# define LIB_SOME 1
# define LIB_OTHER 2
# define WHERE "at file #a, line #l, function #f: "
// (look for syntax hightlighting error at SO xd)
# define LOG_ERROR_SIMPLE(ptr, lib, str) ptr->log ("ERROR " str \
" at library " #lib);
# define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, lib, WHERE str)
LOG_ERROR_SIMPLE (this, LIB_SOME, "doing something")
LOG_ERROR (this, LIB_OTHER, "doing something else")
LOG_ERROR_SIMPLE() writes the stringification of the lib parameter (a macro name surrounded by " ")
but then LOG_ERROR writes the stringification of the macro already expanded ("2"). this is expected, since lib got its expansion before expanding and calling LOG_ERROR_SIMPLE. but this is not what I need.
Basically my question is this: how to avoid macro expansion of a macro function parameter when calling another macro function?
There is a trick I use that avoids macro expansion:
LOG_ERROR(ptr, lib, str, x) LOG_ERROR_SIMPLE(ptr, x##lib, WHERE str)
LOG_ERROR(this, LIB_OTHER, "some error",)
(pasting x and lib produces LIB_OTHER and this value is used to call LOG_ERROR_SIMPLE, its not macro expanded before that call)
There is some way to obtain this same behaviour without using a trick?
I'm doing:
#include <cstdio>
#define FOO 1
#define BAR 2
#define LOG_SIMPLE(ptr, lib, str) printf("%s\n", #lib);
#define LOG(ptr, lib, str) LOG_SIMPLE(ptr, ##lib, str)
int main()
{
LOG_SIMPLE(0, FOO, "some error");
LOG(0, BAR, "some other error");
}
which prints out:
FOO
BAR
Works with MSVC2005 but not with gcc/g++.
EDIT: to make it work with gcc/g++ you can abuse variadic macros:
#include <stdio.h>
#define FOO 1
#define BAR 2
#define LOG_SIMPLE(ptr, str, lib) printf("%s\n", #lib);
#define LOG(ptr, str, lib, ...) LOG_SIMPLE(ptr, str, lib##__VA_ARGS__)
int main()
{
LOG_SIMPLE(0, "some error", FOO);
LOG(0, "some other error", BAR);
LOG(0, "some other error", FOO, BAR);
}
However, it's your discipline not to use the macro with too many parameters. MSVC2005 prints out
FOO
BAR
FOO2
while gcc prints out
FOO
BAR
FOOBAR
If you don't need the expanded lib aliases (i.e. '1' & '2') in your cpp macros, you could also use an enum instead of defined values.
I don't think you can. What you could do, though, is add a layer of macro for it to unpeel in its place:
#define WRAP(x) x
#define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, lib, WHERE WRAP(str))
You almost had it. Use
#define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, ##lib, WHERE str)
On gcc
LOG_ERROR(this, LIB_OTHER, "some error")
yields
this->log ("ERROR " "at file #a, line #l, function #f: " "some error" " at library " "LIB_OTHER");
I would also remove the trailing ';' from your macro so that your code would look like:
LOG_ERROR(this, LIB_OTHER, "some error");