Q_PROPERTY macro within another macro - c++

How to put the Q_PROPERTY macro inside another, helper-macro?
#define SimpleAllinOne(member, _type) \
public: \
void Set##member(_type _arg_##member) \
{ \
m_##member = _arg_##member;\
} \
_type Get##member() const\
{ \
return m_##member;\
} \
private: \
_type m_##member; \
Q_PROPERTY(_type member READ Get##member WRITE Set##member)
.. does not work. Preprocessor output (gcc -E flag or nmake/jom /P flag) shows the (working) setter/getter methods and corresponding member variable but not a single character for the Q_PROPERTY line.
Update: It seems to work with Qt5.1 which expands the user macros properly. Qt4.8 does not work, Qt5.0 has not been tested. See #QTBUG-35 (thanks to ??).

moc in Qt4.x does not recognize Q_ macros within preprocessor macros.
moc in Qt5.x expands the preprocessor macros before parsing the Q_ macros.

You have a bug too in the lines
Set##member##(_type _arg_##member) \
_type Get##member##() const\
because of ##() which is evaluated to
SetArg(
_type GetArg(
by gcc and rejected (MSVC ignores it).
Try the following corrected version and it should work:
#define MachAlles(member, _type) \
public: \
/**
* Set member of type _type.
* #see m_##member for a more detailed description
*/ \
void Set##member(_type _arg_##member) \
{ \
m_##member = _arg_##member;\
} \
/**
* Get member of type _type.
* #see m_##member for a more detailed description
*/ \
_type Get##member() const\
{ \
return m_##member;\
} \
private: \
_type m_##member; \
Q_PROPERTY(_type member READ Get##member WRITE Set##member)

Related

#defined enum on Doxygen

So I have a #define that creates a "MY_ENUM" (minimal version)
#define MY_ENUM(ename, ...) \
namespace ename { \
enum ename { __VA_ARGS__, COUNT }; \
static std::string _Strings[COUNT]; \
static inline size_t size() {return COUNT;} \
}
This generates useful enums that can be created as:
/**
* #brief List of elements
*/
MY_ENUM(enuElements, Element1, Element2, Element3, Element4, Element5, Element6)
But generating the doc with doxygen doesn't seem to work => it mixes one enum with the following and some don't even appear.
I set:
MACRO_EXPANSION = YES
SKIP_FUNCTION_MACROS = NO
PREDEFINED = MY_ENUM(x) =
For what I have read, the answer is a proper setting of PREDEFINED but I haven't achieved, does anyone know how to create a document with this kind of defines?
Edit
Doxygen Version : 1.8.0
About why I think the clue is in PREDEFINED (but I might as well be wrong):
The site of Doxygen when talking about macros
This and this questions on SO
With the following code:
/// \file
#define MY_ENUM(ename, ...) \
namespace ename { \
enum ename { __VA_ARGS__, COUNT }; \
static std::string _Strings[COUNT]; \
static inline size_t size() {return COUNT;} \
}
/**
* #brief List of elements
*/
MY_ENUM(enuElements, Element1, Element2, Element3, Element4, Element5, Element6)
The setting (besides the default settings):
MACRO_EXPANSION = YES
and doxygen 1.9.1 I got:

string concatenation, log4cplus, and MISRA compliance

I am using log4cplus, and my misra-checks for something as innocent-looking as
LOG4CPLUS_INFO(
logger,
std::string("ABC") + std::string("DEF"));
yield (among others) The underlying type of `0L` is implicitly reduced from `8-bit signed char` to {code{bool}}.. This happens also when I put the respective literals rather than wrapping them inside string. I wonder how to fix this. Or, more generally put, how would you concatenate several log messages and yet keep MISRA-checks happy?
I had a look at LOG4CPLUS_INFO and that is a macro defined as:
#if !defined(LOG4CPLUS_DISABLE_INFO)
#define LOG4CPLUS_INFO(logger, logEvent) \
LOG4CPLUS_MACRO_BODY (logger, logEvent, INFO_LOG_LEVEL)
and LOG4CPLUS_MACRO_BODY is defined as:
#define LOG4CPLUS_MACRO_BODY(logger, logEvent, logLevel) \
LOG4CPLUS_SUPPRESS_DOWHILE_WARNING() \
do { \
log4cplus::Logger const & _l \
= log4cplus::detail::macros_get_logger (logger); \
if (LOG4CPLUS_MACRO_LOGLEVEL_PRED ( \
_l.isEnabledFor (log4cplus::logLevel), logLevel)) { \
LOG4CPLUS_MACRO_INSTANTIATE_OSTRINGSTREAM (_log4cplus_buf); \
_log4cplus_buf << logEvent; \
log4cplus::detail::macro_forced_log (_l, \
log4cplus::logLevel, _log4cplus_buf.str(), \
__FILE__, __LINE__, LOG4CPLUS_MACRO_FUNCTION ()); \
} \
} while (0) \
LOG4CPLUS_RESTORE_DOWHILE_WARNING()
and so your MISRA checker will be checking the invocation of the macro. And MISRA likes if statements to be defined explicitly in terms of bool e.g. rather than if(node) it likes if(node!=nullptr) and I think it may have an issue with the last line:
} while (0) \
As 0 is being implicitly cast to bool. You should see if you get the same warning by adding a simple do{}while(0); loop to your code and run your checker again.
And if you want a MISRA safe way of logging, I would avoid the use of macros. You can make a simple logging class with a std::ofstream and a std::mutex and keep it in namespace scope defined as an extern in your header file.

Is it possible to use #define inside a function?

For example, I saw source code like the following. Can we use #define in a function? How does it work? (more information: this code is what I copied from openvswitch source code):
void *
ofputil_put_action(enum ofputil_action_code code, struct ofpbuf *buf)
{
switch (code) {
case OFPUTIL_ACTION_INVALID:
#define OFPAT13_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM:
#include "ofp-util.def"
OVS_NOT_REACHED();
#define OFPAT10_ACTION(ENUM, STRUCT, NAME) \
case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf);
#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf);
#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf);
#include "ofp-util.def"
}
OVS_NOT_REACHED();
}
#define OFPAT10_ACTION(ENUM, STRUCT, NAME) \
void \
ofputil_init_##ENUM(struct STRUCT *s) \
{ \
memset(s, 0, sizeof *s); \
s->type = htons(ENUM); \
s->len = htons(sizeof *s); \
} \
\
struct STRUCT * \
ofputil_put_##ENUM(struct ofpbuf *buf) \
{ \
struct STRUCT *s = ofpbuf_put_uninit(buf, sizeof *s); \
ofputil_init_##ENUM(s); \
return s; \
}
#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
OFPAT10_ACTION(ENUM, STRUCT, NAME)
#define OFPAT13_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
OFPAT10_ACTION(ENUM, STRUCT, NAME)
#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
void \
ofputil_init_##ENUM(struct STRUCT *s) \
{ \
memset(s, 0, sizeof *s); \
s->type = htons(OFPAT10_VENDOR); \
s->len = htons(sizeof *s); \
s->vendor = htonl(NX_VENDOR_ID); \
s->subtype = htons(ENUM); \
} \
\
struct STRUCT * \
ofputil_put_##ENUM(struct ofpbuf *buf) \
{ \
struct STRUCT *s = ofpbuf_put_uninit(buf, sizeof *s); \
ofputil_init_##ENUM(s); \
return s; \
}
#include "ofp-util.def"
#define is a preprocessor directive: it is used to generate the eventual C++ code before it is handled to the compiler that will generate an executable. Therefore code like:
for(int i = 0; i < 54; i++) {
#define BUFFER_SIZE 1024
}
is not executed 54 times (at the preprocessor level): the preprocessor simply runs over the for loop (not knowing what a for loop is), sees a define statement, associates 1024 with BUFFER_SIZE and continues. Until it reaches the bottom of the file.
You can write #define everywhere since the preprocessor is not really aware of the program itself.
Sure this is possible. The #define is processed by the preprocessor before the compiler does anything. It is a simple text replacement. The preprocessor doesn't even know if the line of code is inside or outside a function, class or whatever.
By the way, it is generally considered bad style to define preprocessor macros in C++. Most of the things they are used for can be better achieved with templates.
You can use it inside a function, but it is not scoped to the function. So, in your example, the second definitions of a macro will be a redefinition and generate an error. You need to use #undef to clear them first.
You can use #define anywhere you want. It has no knowledge of functions and is not bound by their scope. As the preprocessor scans the file from top-to-bottom it processes #defines as it sees them. Do not be misled (by silly code like this!) into thinking that the #define is somehow processed only when the function is called; it's not.
How does it work? All C/C++ files are first processed by... the preprocessor.
It doesn't know anything about C nor C++ syntax. It simply replaces THIS_THING with ANOTHER THING. That's why you can place a #define in functions as well.
Sure. #define is handled by the preprocessor which occurs well before the compiler has any sense of lines of code being inside functions, inside parameters lists, inside data structures, etc.
Since the preprocessor has no concept of C++ functions, it also means that there is no natural scope to macro definitions. So if you want to reuse a macro name, you have to #undef NAME to avoid warnings.

C++ Preprocessor macro loop __VA_ARGS__ 1 vs 2+ arguments

I'm using the macros from this post looping through my arguments. Everything works great! However, is there a way to combine these two CCB_CREATE and CCB_CREATE_MORE?
I need to extract the first argument object_type to write additional code. The additional object_types will be using the FOR_EACH loop to insert into the map.
The compiler complaints when I only have one argument when using CCB_CREATE_MORE(Type1). To fix that I made another macro to handle that CCB_CREATE(Type1). Hoping to find a clever solution to combine these two into one elegant macro. Any ideas?
#define INSERT_LOADER_MAP(object_type) loader_map.insert(make_pair(#object_type, object_type##Loader::loader()))
#define CCB_CREATE_MORE(object_type,...) \
static CCNode * create##object_type##Node() { \
std::map<std::string, CCNodeLoader*> loader_map; \
std::string classname = #object_type; \
FOR_EACH(INSERT_LOADER_MAP,object_type,__VA_ARGS__); \
return loadCCBFile((classname + ".ccbi").c_str(), loader_map); \
}
#define CCB_CREATE(object_type) \
static CCNode * create##object_type##Node() { \
std::map<std::string, CCNodeLoader*> loader_map; \
std::string classname = #object_type; \
INSERT_LOADER_MAP(object_type); \
return loadCCBFile((classname + ".ccbi").c_str(), loader_map); \
}
The compiler is likely complaining about the trailing comma when the variadic arguments list is empty. GCC and Visual Studio compilers support the non-standard extension ##__VA_ARGS__ to suppress the trailing comma:
#define FOO(fmt, ...) printf(fmt, ##__VA_ARGS__)
The Visual Studio compilers will also suppress the trailing comma even without the ## extension.
See GCC documentation here, and Visual Studio documentation here.
If you need a standards-compliant solution, there is one detailed in an answer to this question.
So if you are using either gcc or Visual Studio, you should be able to use your original macro with this simple change:
#define CCB_CREATE(object_type,...) \
static CCNode * create##object_type##Node() { \
std::map<std::string, CCNodeLoader*> loader_map; \
std::string classname = #object_type; \
FOR_EACH(INSERT_LOADER_MAP,object_type,##__VA_ARGS__); \
return loadCCBFile((classname + ".ccbi").c_str(), loader_map); \
}
Edit:
You would need to use the ##__VA_ARGS__ extension in the FOR_EACH() macro as well, or the more elegant modification suggested by ugoren.
#define FOR_EACH(what, x, ...) FOR_EACH_(FOR_EACH_NARG(x, ##__VA_ARGS__), what, x, __VA_ARGS__)
In addition to Chris Olsen's suggestion, a slight change to the FOR_EACH macro is needed:
#define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__)
As a result, FOR_EACH(X, a) will become X(a) (instead of X(a); X();). This eliminates an empty INSERT_LOADER_MAP invocation.

Concatenating qt-specific keyword and macro argument with a space in between

My problem is quite simple. I want the following macro
#define PROXYPASS(name, param) \
void MyClass::sl_name(param _param) { \
emit name(_param); \
}
to expand PROXYPASS(clientAdded, Client*) to:
void MyClass::sl_clientAdded(Client* _param) { \
emit clientAdded(_param); \
}
but since it ain't working i.e. it still shows just sl_name instead of sl_clientAdded. So, this is what I'm using:
#define PROXYPASS(name, param) \
void MyClass::sl_ ## name(param _param) { \
emit ## name(_param); \
}
It works fine, other than the fact that it expands to:
void MyClass::sl_clientAdded(Client* _param) { \
emitclientAdded(_param); \
}
Everything is fine other than the fact that there is no space between emit and clientAdded i.e. it expands to emitclientAdded instead of emit clientAdded. So how do I go about doing it? Is there a way to add spaces, or must I look for another way. A lot of googling has got my hopes down due to the following statement: Whether it [gcc pre-processor] puts white space between the tokens is undefined.
My other failed attempts include
emit ## ## name(_param);
emit ## /* */ ## name(_param);
emit ## \ ## name(_param);
emit /* */ ## name(_param);
emit ## space ## name(_param); [#define space \ ]
Any help is greatly appreciated.
NOTE: Preprocessor output and macro expansion checked using gcc -E myclass.cpp.
Just put nothing there, you don't need to concatenate anything:
#define PROXYPASS(name, param) \
void MyClass::sl_ ## name(param _param) { \
emit name(_param); \
}