
I came up with some macros the other day trying to solve a kernel problem and I haven't seen them anywhere else and if I found one, I sure would have stolen it. :) I used this to have a single function-like macro service different numbers of parameters, essentially adding "optional parameter" support so I didn't have to have different version of the macro. IF_NONEMPTY(test, result) expands to result if test is non-empty, empty otherwise. IS_NONEMPTY(arg) expands to 0 if arg is empty, 0x1 if it isn't. OPT_OFFSETOF(type, member) isn't very useful in C++, but it is an example of how the above can be used. It expands to a compiler-time constant that is the offset of the member in the struct or union type, unless member isn't specified, in which case it's zero. #define __JUNK junk, #define _if_nonempty(arg1_or_junk, result) __if_nonempty(arg1_or_junk, result) #define __if_nonempty(__ignored, result, ...) result #define CONCAT_TOKEN(a, b) _concat_token(a, b) #define _concat_token(a, b) a ## b #define IF_NONEMPTY(test, result) _if_nonempty(__JUNK##test, result) #define IS_NONEMPTY(arg) CONCAT_TOKEN(0, IF_NONEMPTY(arg, x1)) #define OPT_OFFSETOF(type, m) ((size_t) &((*((type *)0)) IF_NONEMPTY(m,.)m))

On 8 May 2012 10:24, Daniel Santos <danielfsantos@att.net> wrote:
I came up with some macros the other day trying to solve a kernel problem and I haven't seen them anywhere else and if I found one, I sure would have stolen it. :) I used this to have a single function-like macro service different numbers of parameters, essentially adding "optional parameter" support so I didn't have to have different version of the macro.
IF_NONEMPTY(test, result) expands to result if test is non-empty, empty otherwise. IS_NONEMPTY(arg) expands to 0 if arg is empty, 0x1 if it isn't. OPT_OFFSETOF(type, member) isn't very useful in C++, but it is an example of how the above can be used. It expands to a compiler-time constant that is the offset of the member in the struct or union type, unless member isn't specified, in which case it's zero.
There's BOOST_PP_IS_EMPTY in <boost/preprocessor/facilities/is_empty.hpp> although it isn't publicized as it won't work on some preprocessors. I haven't look closely enough to see how it compares.

On 05/08/2012 12:12 PM, Daniel James wrote:
There's BOOST_PP_IS_EMPTY in <boost/preprocessor/facilities/is_empty.hpp> although it isn't publicized as it won't work on some preprocessors. I haven't look closely enough to see how it compares. Cool, thanks! This one really does a lot of compiler checks and mine is gcc-specific. I came up with a much better variation (below). As far as the standards, I think an empty pre-processor parameter is only well-formed in C++03 or 11 and in C99 and later.
#define __JUNK junk, #define _iff_empty(arg1_or_junk, t, f) __iff_empty(arg1_or_junk, f, t) #define __iff_empty(__ignored1, __ignored2, result, ...) result #define IFF_EMPTY(test, t, f) _iff_empty(__JUNK##test, t, f) #define IS_EMPTY(test) IFF_EMPTY(test, 1, 0) While this works in gcc, it doesn't deal with any compiler quirks & differences, sorry. Daniel

On 5/8/2012 5:24 AM, Daniel Santos wrote:
I came up with some macros the other day trying to solve a kernel problem and I haven't seen them anywhere else and if I found one, I sure would have stolen it. :) I used this to have a single function-like macro service different numbers of parameters, essentially adding "optional parameter" support so I didn't have to have different version of the macro.
IF_NONEMPTY(test, result) expands to result if test is non-empty, empty otherwise. IS_NONEMPTY(arg) expands to 0 if arg is empty, 0x1 if it isn't. OPT_OFFSETOF(type, member) isn't very useful in C++, but it is an example of how the above can be used. It expands to a compiler-time constant that is the offset of the member in the struct or union type, unless member isn't specified, in which case it's zero.
#define __JUNK junk, #define _if_nonempty(arg1_or_junk, result) __if_nonempty(arg1_or_junk, result) #define __if_nonempty(__ignored, result, ...) result #define CONCAT_TOKEN(a, b) _concat_token(a, b) #define _concat_token(a, b) a ## b
#define IF_NONEMPTY(test, result) _if_nonempty(__JUNK##test, result)
If the 'test' token is not concatenable you will get a compiler error. This is the major weakness of your implementation and extends to the 'arg' token in your next macro. For another IS_EMPTY implementation, almost entirely based on code Paul Mensonides posted on the Internet for use with variadic macros, see the BOOST_VMD_IS_EMPTY macro in my own variadic macro library in the Boost sandbox. It still has a flaw, although a different ( and IMO a lesser ) one than your implementation. As Paul Mensonides has stated, there is no version of IS_EMPTY which can be created which is perfect for a 100% conformant C++ preprocesor. Eddie Diener
#define IS_NONEMPTY(arg) CONCAT_TOKEN(0, IF_NONEMPTY(arg, x1)) #define OPT_OFFSETOF(type, m) ((size_t)&((*((type *)0)) IF_NONEMPTY(m,.)m))
_______________________________________________ Unsubscribe& other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (3)
-
Daniel James
-
Daniel Santos
-
Edward Diener