consider the following macro:
#define checkExists(map, it, value) {\
it = map.find(value);\
if(it == map.end()){\
if(!strcmp(typeid(value).name(), "Ss")){ /* value is an std::string */\
manageError(ERR_CANT_FIND_RESSOURCES, "in %s __ failed to find %s in map %s", __FUNCTION__, value.c_str(), #map);\
\
}else if(!(strcmp(typeid(value).name(), "Pc") * strcmp(typeid(value).name(), "PKc"))){ /* value is either char* or const char* */\
manageError(ERR_CANT_FIND_RESSOURCES, "in %s __ failed to find %s in map %s", __FUNCTION__, value #map); /* problem here because for gcc value could be an std::string */ \
\
} else \
manageError(ERR_CANT_FIND_RESSOURCES, "in %s __ failed to find 0x%04X in map %s", __FUNCTION__, value #map); /* problem here because for gcc value could be an std::string */\
}\
}
manageError is a also a macro that calls a function logWarning which only accepts only fundamental types (eg int, char* ...). The prototypes are:
#define manageError(error_code, error_str, ...) {\
{\
logWarning(error_str, ##__VA_ARGS__);\
return error_code;\
}\
}
int logWarning(const char* printf_format, ...);
So if my value is an std::string, I am giving manageError a const char *.
It's seems like checkExists isn't evaluated compile time... so gcc being very clever, it doesn't allow me the last two manageError calls, because it sees value as an std::string or it's impossible because std::string is only possible in the first case.
For example, this doesn't work:
std::string foo;
checkExists(myMap, myMapIterator, foo);
gcc output:
error: cannot pass objects of non-trivially-copyable type 'const string {aka const struct std::basic_string<char>}' through '...'
Do you know how I can solve this issue ?
Edit
the idea of that mecanism is to be able to leave the current function if an error occured. For example:
int func(){
std::string foo;
checkExists(myMap, myMapIterator, foo); //leaves the function if foo is not found inside myMap
return 0;
}
so I have to use macro to be able to leave the function (not possible for me to use templates).
I solved the problem by converting value to std::string no matter the input type.
#define checkExists(map, it, value) {\
it = map.find(value);\
if(it == map.end()){\
std::stringstream tmpSs;\
if(!(strcmp(typeid(value).name(), "Pc") * strcmp(typeid(value).name(), "PKc") * strcmp(typeid(value).name(), "Ss"))){\
tmpSs << value;\
}else{\
tmpSs << "0x" << std::uppercase << std::setfill('0') << std::setw(4) << std::hex << value; /* converting value to hex format */\
}\
\
manageError(ERRCAN_T_FIND_RESSOURCES, "in %s __ failed to find %s in map %s", __FUNCTION__, tmpSs.str().c_str(), #map);\
}\
}
Related
I'm trying to redefine a Variadic Macro to use cout instead of printf. Here's the original code:
#define LOGE(...) PRINT_LEVEL(1, __VA_ARGS__);
#define PRINT_LEVEL(level,...) do { \
if (debug_components.DEBUG_COMPONENT >= level) \
{ printf("[%s]: ", levels_strings[level-1]); printf(__VA_ARGS__); printf("\n"); } \
}while(0)
I converted this to the following to use cout instead of printf:
#define PRINT_LEVEL(level,...) do { \
if (debug_components.DEBUG_COMPONENT >= level) \
{ std::string argString; sprintf(argString, __VA_ARGS__); std::cout << "[" << levels_strings[level-1] << "]" << argString << "\n";} \
}while(0)
For some reason, __VA_ARGS__ works fine with printf, but NOT sprintf. It also does not work with cout. I'd like to know the correct way to convert __VA_ARGS__ to a string, or failing that, the correct way to just print it out using cout.
sprintf takes an extra argument, the data buffer to write the output to. You can't swap out printf for sprintf without making the changes to provide that buffer. It also doesn't return a pointer to the string, so you can't assign the result to a std::string and expect it to work. If you're operating unsafely (assuming a maximum buffer length), something as simple as:
#define PRINT_LEVEL(level,...) do { \
if (debug_components.DEBUG_COMPONENT >= level) \
{
char buf[1024];
sprintf(buf, __VA_ARGS__); std::cout << "[" << levels_strings[level-1] << "]" << buf << "\n";} \
}while(0)
would work (and with truncation, could be done with safety if not reliably via snprintf), but if you're using C++ types anyway, you might want to look at a non-printf-y solution
I was using sprintf wrong. Here's the correct code:
char argString[1024]; sprintf(argString, __VA_ARGS__);
Now argString holds the value of VA_ARGS.
Some time ago, I made this beautiful assert macro for c and c++ programs
#define ASSERT(truthy, message) \
if (!(truthy)) \
{\
cout << message << " on line " << __LINE__ << " in file " << __FILE__ << ". Check was " << #truthy << endl;\
}
Scatter ASSERT calls throughout your code, and it will warn you whenever the truthy value is not truthy! Very handy during development to remind you of potential mistakes.
ex
ASSERT(filesFound > 0, "Couldn't find any files, check your path!");
When filesFound is 0, the macro will print out
Couldn't find any files, check your path! on line 27 in file
openFiles.c. Check was filesFound > 0
Now what I want it to print, to give me even more relevant information, is the value of any variables passed into the truthy parameter. Like this
Couldn't find any files, check your path! on line 27 in file
openFiles.c. Check was filesFound > 0, filesFound is 0
This seems lisp-like territory, I wonder, is there any black magic c preprocessing that I can use to evaluate variables and functions to their values, without evaluating the truthy statement?
I assume to be disappointed.
An alternative solution which I've always used is to support varargs in the macro and then force the assert user to specify the relevant message / variables - it's a little bit of extra work each time, but on the plus side you can get exactly the formatting that you want and include information not available in the "truthy" bit, e.g:
#define ASSERT(truthy, message, ...) \
if (!(truthy)) \
{\
MyAssertHandler(__LINE__, __FILE__, #truthy, message, ##__VA_ARGS__);
}
Then you're handler is just a fairly standard var-arg function that can use e.g. vsnprintf to generate the message and output it, e.g. off the top of my head:
void MyAssertHandler(int line, const char* file, const char* expressionStr, const char* format, ...)
{
// Note: You probably want to use vsnprintf instead to first generate
// the message and then add extra info (line, filename, etc.) to
// the actual output
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
// Log to bug database, DebugBreak() if a debugger is attached, etc.
}
usage:
ASSERT(IsBlah(), "BlahBlah: x = %.2f, name = %s", GetX(), GetName());
I cannot imagine a way to do it... except by passing another parameter
#define ASSERT_PARAM(truthy, message, param) \
if (!(truthy)) \
{\
cout << message << " on line " << __LINE__ << " in file " << __FILE__ << ". Check was " << #truthy << ", value was " << param << endl;\
}
You would use it that way:
ASSERT_PARAM(filesFound > 0, "Couldn't find any files, check your path!", filesFound);
getting:
Couldn't find any files, check your path! on line 27 in file openFiles.c. Check was filesFound > 0, value was 0
What you are trying to do sounds very complicated. I'm afraid in C++ it's not possible.
Technically what you are evaluating is a bool expression so you can pass it to a parser whenever the assertion fails. The parser then will build the expression tree, get the leaves (elements of the expression) and return them. The returned values then should be printed out. To do that you will need support for reflection which is actually not supported in C++ AFAIK.
Maybe not the dream solution, but you can pass whole statements to a macro.
#define ASSERT(trusty, action) if (!trusty) { action }
ASSERT(trusty, cout << a << b;)
ASSERT(trusty, printf("%d, %f\n", a, b);)
I think you can split up the truthy Expression like they do it in the first answer here and then you can probably print the individual values. But I'm not sure if it actually works.
The printing could then be resulved using a variadic template function
Perhaps you could compromise and only allow 2 variables and 1 operator in the assertion expression? If so, you could make an ad hoc solution like this:
#include <iostream>
#include <string>
#define STRINGIFY(x) #x
#define BIN_ASSERT(obj1, op, obj2, msg) \
if(!(obj1 op obj2)) \
{ \
std::cout << msg << " on line " << __LINE__ \
<< " in file " << __FILE__ \
<< "." << std::endl \
<< "Check was " \
<< STRINGIFY(obj1) STRINGIFY(op) STRINGIFY(obj2) \
<< "." << std::endl \
<< "Operator " << #obj1 << ": " << obj1 \
<< "." << std::endl \
<< "Operator " << #obj2 << ": " << obj2 \
<< "." << std::endl; \
}
int main (void)
{
int x = 2;
int y = 3;
std::string s1 = "hello";
std::string s2 = "world";
BIN_ASSERT(1, +, -1, "Value zero"); std::cout << std::endl;
BIN_ASSERT(x, ==, y, "Numbers not equal"); std::cout << std::endl;
BIN_ASSERT(s1, ==, s2, "Strings not equal"); std::cout << std::endl;
}
Output:
Value zero on line 30 in file test.c.
Check was 1+-1.
Operator 1: 1.
Operator -1: -1.
Numbers not equal on line 31 in file test.c.
Check was x==y.
Operator x: 2.
Operator y: 3.
Strings not equal on line 32 in file test.c.
Check was s1==s2.
Operator s1: hello.
Operator s2: world.
I wonder if having the macro take a message is really that useful. A failed assertion is a message to the developer that there is a bug in the code that caused an exceptional behaviour or put the program in an unacceptable state. The user has less to do with it (if they even have access to the source code).
The code below defines an ASSERT macro that takes a boolean expression, evaluates it and prints an informational message. The message contains a value that you've asked to inspect upon failing the assertion.
The macro, just like the standard assert() macro (in <cassert>) goes on to call abort() (from <cstdlib>) to cause an abnormal program termination. This is what you want, because the program entered a state in which it didn't know what more to do.
I'm using std::printf() here for brevity. You do whatever you want.
#include <cstdlib>
#include <cstdio>
#define ASSERT(value, inspect) \
if (!(value)) { \
std::printf("ASSERTION FAILED: '%s', %s is %d: %s#%s:%d\n", #value, \
#inspect, inspect, __func__, __FILE__, __LINE__); \
abort(); \
}
int foo() { return 42; }
int main()
{
// ...
ASSERT(foo() - 40 == 1, foo());
//...
}
Program run:
$ ./a.out
ASSERTION FAILED: 'foo() - 40 == 1', foo() is 42: main#prog.cc:16
Abort
It's not possible to do exactly what you ask for without adding more parameters to the macro. At some point you'll have to stop and realize that you're spending time on creating a text string that you do not want to see.
You need to build an expression 'grabber' / builder.
The macro would become something like:
#define ASSERT_PARAM(truthy, message, param) \
if (!(truthy)) \
{\
Grabber g;
g << #truthy; // grab expression as string
g % truthy; // grab expression and values
cout << message << " on line " << __LINE__ << " in file " << __FILE__ << ". Check was " << #truthy << ", value was " << param << endl;\
cout << g; \
}
What does Grabber do?
It is a bunch of crazy C++ that builds up an expression. It would overload every operator to 'grab' the params of the operator. Every operator returns a reference to the grabber, so it can grab the next operator. ie
Grabber g;
g % filesFound > 0;
Since % (and * and /) have high precedence, the above parses like:
((g % filesFound) > 0)
If template<typename T> Grabber::operator%(T const & val) just records (or prints) the value passed in (ie filesFound), and - importantly - returns itself (g) so that it becomes part of the next expression: ie it becomes g > 0. Causing template<typename T> Grabber::operator>(T const & val) to be called, and > 0 to be recorded.
Then cout << g can spew out everything grabbed.
As mentioned above "It is possible — the Catch library does it. But it’s hellishly difficult".
P.S. you should wrap your macro in a do ... while 0 like this:
#define ASSERT_PARAM(truthy, message, param) \
do \
{ \
if (!(truthy)) \
{\
cout << message << " on line " << __LINE__ << " in file " << __FILE__ << ". Check was " << #truthy << ", value was " << param << endl;\
cout << g; \
} \
} while (0)
What you have currently means that this is valid code:
ASSERT(foo != 0)
else
{
}
And this is NOT valid code:
if (foo != nullptr)
ASSERT(foo->bar != nullptr);
else
x = 10;
Surprisingly, I solved a similar problem before, but I'm not sure if it could help you in this case.
The original solution was proposed by Andrei Alexandrescu in the article Enhancing Assertions, and with no question, relying on some macro tricks.
This amazing facility can be used as the following:
string s1, s2;
...
SMART_ASSERT(s1.empty() && s2.empty())(s1)(s2);
And if something goes wrong, the message would be displayed
Assertion failed in matrix.cpp: 879412:
Expression: 's1.empty() && s2.empty()'
Values: s1 = "Wake up, Neo"
s2 = "It's time to reload."
Be noted that, the SMART_ASSERT can capture infinite variables, theoretically.
For implementation details, please check out the article.
I am trying to create a simple logging class with just static methods but i get troubles when i try to log some const char* variable and wonder why. It says Error: expression must have integral or unscoped enum type. I looked for it at stackoverflow and google but somehow it doesn't help me to get it right.
The logging methods are this:
void Logger::log(const char* message){
#ifdef _DEBUG
std::cout<< "[INFO]" << message << std::endl;
#endif
}
void Logger::err(const char* message){
#ifdef _DEBUG
std::cout << "[ERROR]" << message << std::endl;
#endif
}
And i am trying to call them here:
char* Config::getConfigValue(const char* name){
if (m_doc.first_node())
{
xml_node<>* node = m_doc.first_node()->first_node(name);
if (node)
{
Logger::log("Getting value: " + name + ": "+ node->value());
return node->value();
}
}
Logger::log("Getting value: " + name + " FAILED!");
return 0;
}
Am i totaly wrong with the idea of such a simple logger?
And should i do #ifdef at every point where i log or can i do it like this?
For any hints to solve this issue and to help me to get a "good" logger i would be greatful.
The problem has nothing to do with your logging. You cannot concatenate C strings using +.
"Getting value: " + name // Not going to work.
If you are in c++ anyways, I would stick with std::string when possible because that one does support + for concatenation.
char * or char const * is a pointer type, not a class or struct, thus does not support concatenation using + operator.
You're using C++, so use the C++ way of handling strings : replace const char * with const std::string &.
The expression
"Getting value: " + name + " FAILED!"
where name is const char* name is an error because there is no operator+ in global namespace that takes const char*. You have to use strcat, strcpy, etc.
In C++ you should use std::string which is very flexible ( i.e resizes dynamically):
char* Config::getConfigValue( std::string name){
//...
Logger::log("Getting value: " + name + ": "+ node->value());
}
I want to write a macro that takes as its only argument a list of std::ostream& operator<< concatenated objects and passes the consolidated string as a single std::string object to a function. The ability to pass the consolidated string to a function is key; in the example below I am aware that the example itself could be rewritten to work simply by defining the macro to ERR_MSG(inputs) std::cout << "ERROR: " << inputs, but sending the output to std::cout is not the goal, it's just the test objective I chose for the example.
I'm using GCC 4.1.2 (Red Hat 4.1.2-52) and upgrading it is not an option. Here's a very boiled-down version of what I've tried:
#include <sstream>
#include <iostream>
#define ERR_MSG(inputs) errMsg(std::ostringstream().str()) // 1
#define ERR_MSG(inputs) errMsg((std::ostringstream()<<inputs).str()) // 2
<aReturnType> errMsg(const std::string& msg) // use with 1 & 2
{
std::cout << "\nERROR: " << msg << "\n\n";
return <someObjectCreatedBasedOnTheInput>;
}
#define ERR_MSG(inputs) errMsg(std::ostringstream()<<inputs) // 3
<aReturnType> errMsg(const std::ostringstream& msg) // use with 3
{
std::cout << "\nERROR: " << msg.str() << "\n\n";
return <someObjectCreatedBasedOnTheInput>;
}
int main()
{
ERR_MSG("A number: " << 24 << ", a char: " << 'c' << ", that's all!");
}
Macro #1 compiles, but of course prints nothing but "" for the message. Neither macros 2 & 3 compile, with the following errors:
#define ERR_MSG(inputs) errMsg((std::ostringstream()<<inputs).str()) // 2
error: ‘struct std::basic_ostream<char, std::char_traits<char> >’ has no member named ‘str’
#define ERR_MSG(inputs) errMsg(std::ostringstream()<<inputs) // 3
no matching function for call to ‘errMsg(std::basic_ostream<char, std::char_traits<char> >&)’
note: candidates are: char* errMsg(const std::string&)
note: char* errMsg(const std::ostringstream&)
I am not interested in how I could rewrite this without macros; I can do that quite easily myself.
=== UPDATE: ===
I forgot to mention that in its real use case, the function called by the macro returns an object that may be used by the caller of the macro. That invalidates any macro implementations that cannot be implemented in a single expression whose result is the returned type of the function called by the macro. The "do nothing" implementation of the macro (for release builds) will simply pass an empty std::string to the function regardless of what the "inputs" are. Sorry for not mentioning that earlier.
Your current problem is that all of the various operator<< functions return an ostream&, not an ostringstream&. You can solve that with a simple cast:
#define ERR_MSG(inputs) errMsg((static_cast<std::ostringstream&>(std::ostringstream().flush() << inputs)).str())
The flush is needed because std::ostringstream() is a temporary. Therefore, you can't call functions on it that take an lvalue reference (ie: std::ostream&). Functions like most operator<< variants. All the flush call does is return the this pointer as an lvalue reference.
If you are willing to use some GCC extension, you could declare an actual ostringstream inside the macro in a block, so that the .str() method can be used without casting:
#define ERR_MSG(inputs) \
do { std::ostringstream _s_; _s_<<inputs;errMsg(_s_.str()); } while(false)
Demo: http://ideone.com/clone/y56lc
Use do { } while (false) idiom to make a few lines macro.
#define ERR_MSG(inputs) \
do { \
std::ostringstream osERR_MSG; \
osERR_MSG << inputs; \
errMsg(osERR_MSG.str()); \
} while (false)
int main() {
if (1) ERR_MSG("A number: " << 24 << ", a char: " << 'c' << ", that's all!");
else return 0;
}
The reason I made such strange name osERR_MSG is to avoid as much as possible cases like this:
int osERR_MSG = 7;
ERR_MSG(osERR_MSG);
#include <sstream>
#include <iostream>
#define ERR_MSG(inputs) errMsg(std::ostringstream().flush()<<inputs)
int errMsg(std::ostream& os)
{
std::ostringstream& oss(static_cast<std::ostringstream&>(os));
const std::string& str(oss.str());
std::cout << "\nERROR: " << str << "\n\n";
return str.length();
}
int main()
{
int i = ERR_MSG("A number: " << 24 << ", a char: " << 'c' << ", that's all!");
std::cout << i << "\n";
}
I'd not create an std::ostringstream but rather have a function called from the destructor of a class derived from std::ostream. Here is an example of this approach:
#include <sstream>
#include <iostream>
void someFunction(std::string const& value)
{
std::cout << "someFunction(" << value << ")\n";
}
void method(std::string const& value)
{
std::cout << "method(" << value << ")\n";
}
class FunctionStream
: private virtual std::stringbuf
, public std::ostream
{
public:
FunctionStream()
: std::ostream(this)
, d_function(&method)
{
}
FunctionStream(void (*function)(std::string const&))
: std::ostream(this)
, d_function(function)
{
}
~FunctionStream()
{
this->d_function(this->str());
}
private:
void (*d_function)(std::string const&);
};
int main(int ac, char* av[])
{
FunctionStream() << "Hello, world: " << ac;
FunctionStream(&someFunction) << "Goodbye, world: " << ac;
}
The example use doesn't use a macro but this can be wrapped easily around the above use of FunctionStream(). Note, that in a macro you probably want to make sure that the type seen by the user of the macro is of type std::ostream& rather than a temporary type so it can be used directly with user defined output operators. To this end you should have an insertion for one of the types directly supported by std::ostream which doesn't have any effect but returns an std::ostream&, for example:
#define SomeMacro(output) FunctionStream(&someFunction) << "" << output
Reinstating Nicol's answer as its the best so far:
Your current problem is that all of the various operator<< functions return an ostream&, not an ostringstream&. You can solve that with a simple cast:
#define ERR_MSG(inputs) errMsg((static_cast<std::ostringstream&>(std::ostringstream().flush() << inputs)).str())
Of course, this still has the problem (like all the answers here) that something like
ERR_MSG(x ? "x is true" : "x is false")
will misbehave in an odd and confusing manner.
This is my assert function (it wont compile "error C2110: '+' : cannot add two pointers"):
#define CHAR(x) #x
template<typename T>
inline void ASSERT(T x)
{
if(!x)
{
std::string s("ERROR! Assert " + CHAR(x) + " failed. In file " + __FILE__ +
" at line " + __LINE__ + ".");
std::wstring temp(s.length(), L' ');
std::copy(s.begin(), s.end(), temp.begin());
getLogger().Write(temp);
}
}
Any idea of how to fix it?
String Literals are easily reduced to char pointers, which cannot be added as you try to do with "ERROR! Assert " + CHAR(x) + " failed. In file ".... However, C++ has the handy feature of doing this automatically before compilation! (the preprocessor does this). Even better, it has a handy tool for making wide strings at compile time. So, you want:
#define _T(x) L ## x
#define CHAR(x) #x
#define CHAR2(x) CHAR(x)
#define ASSERT(x) ASSERT2(x, CHAR(x), __FILE__, CHAR2(__LINE__))
#define ASSERT2(x, t, f, l) \
if(!x) \
getLogger().Write(L"ERROR! Assert " _T(t) L" failed. In file " _T(f) L" at line " _T(l) L".");
http://ideone.com/0ibcj
The compiler error is quite clear; you are trying to apply the + operator to string literals. A quick way to fix it is enclosing the first string literal in std::string().
As #James McNellis pointed out, note that FILE and LINE will point to the file and line of the assert function declaration.
You cannot use the + operator to concatenate two char*s; you need printf or some sort of thing for that.
"ERROR! Assert " is a null-terminated, C-style string. You can't execute operator+ on it.
A few issues:
Generally an assert should break into the debugger or dump if one is not attached. This will not.
As already mentioned, your LINE and FILE require use in a macro
You need a couple "helper" macros to get the strings working properly
Try something along these lines:
#define ASSERT_QUOTE_(x) #x
#define ASSERT_QUOTE_(x) ASSERT_QUOTE_(x)
#define MY_ASSERT(cond) \
if(cond) {} else { \
std::stringstream ss; \
ss << "ERROR! Assert " << ASSERT_QUOTE(cond) << " failed. In file " << __FILE__ << " at line " << __LINE__ << "."; \
getLogger().Write(ss.str()); \
}
Be careful trying to use STL here however. I suggest you have your logger's Write() function take variable arguments and process them with printf() or perhaps boost::format