
Hello Using the BOOST_PP_IS_EMPTY macro with string literal as parameter causes compiler warning: warning: pasting "BOOST_PP_IS_EMPTY_DEF_" and ""AA"" does not give a valid preprocessing token In order to avoid this warning I have reimplemented this macro as it is shown below. Could something similar be implemented by the preprocessor library. Cheers, Sergei #include <boost/preprocessor/if.hpp> #include <boost/preprocessor/tuple.hpp> #include <boost/preprocessor/facilities/is_empty.hpp> #define MY_BOOST_PP_IS_EMPTY(x) MY_BOOST_PP_IS_EMPTY_I(MY_BOOST_PP_IS_EMPTY_HELPER x) #define MY_BOOST_PP_IS_EMPTY_I(contents) MY_BOOST_PP_IS_EMPTY_II( contents() ) #define MY_BOOST_PP_IS_EMPTY_II(contents) MY_BOOST_PP_IS_EMPTY_III( contents ) #define MY_BOOST_PP_IS_EMPTY_III(contents) BOOST_PP_TUPLE_ELEM( 2, 0, ( MY_BOOST_PP_IS_EMPTY_DEF_ ## contents ) ) #define MY_BOOST_PP_IS_EMPTY_HELPER() MY_BOOST_PP_IS_EMPTY_TRUE #define MY_BOOST_PP_IS_EMPTY_DEF_MY_BOOST_PP_IS_EMPTY_TRUE 1 , #define MY_BOOST_PP_IS_EMPTY_DEF_MY_BOOST_PP_IS_EMPTY_HELPER 0 , #define TEST_CASE_1( x ) BOOST_PP_IF( BOOST_PP_IS_EMPTY( x ), is empty, x ) #define TEST_CASE_2( x ) BOOST_PP_IF( MY_BOOST_PP_IS_EMPTY( x ), is empty, x ) TEST_CASE_1( "" ) TEST_CASE_1( "AA" ) TEST_CASE_1( AA ) TEST_CASE_1( ) TEST_CASE_2( "" ) TEST_CASE_2( "AA" ) TEST_CASE_2( AA ) TEST_CASE_2( )

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Serguei KOLOS Sent: Tuesday, February 21, 2006 12:42 AM To: boost@lists.boost.org Subject: [boost] problem with BOOST_PP_IS_EMPTY macro
Hello
Using the BOOST_PP_IS_EMPTY macro with string literal as parameter causes compiler warning: warning: pasting "BOOST_PP_IS_EMPTY_DEF_" and ""AA"" does not give a valid preprocessing token
That macro is 1) not a library interface (so why are you using it?) and 2) is not a general purpose emptiness detector (there is no such thing). There are very specific constraints on what the input is supposed to be.
#include <boost/preprocessor/if.hpp> #include <boost/preprocessor/tuple.hpp> #include <boost/preprocessor/facilities/is_empty.hpp>
#define MY_BOOST_PP_IS_EMPTY(x) MY_BOOST_PP_IS_EMPTY_I(MY_BOOST_PP_IS_EMPTY_HELPER x)
First, this will fail if 'x' is a parenthesized expression. I.e. if 'x' is () or (a) or (a, b), etc.. It will also fail if 'x' ends with a function-like macro name. Second, passing nothing--as in TEST_CASE_1( ) and TEST_CASE_2( )--is results in undefined behavior in current C++ (which will give you warnings on many preprocessors). Third, even with placemarkers from C99 (well-defined semantics for empty arguments), you still cannot generally test emptiness. Trust me, there is *no* way to do it. The best that you can do is to contrain the input to a subset of non-pathological input. The macros in the library, IS_EMPTY, IS_1, and IS_EMPTY_OR_1 are all designed for a very specific purpose: testing flags such as: #define CONFIG_A #define CONFIG_B 1 #define CONFIG_C 0 IS_EMPTY(CONFIG_A) // 1 IS_EMPTY(CONFIG_B) // 0 IS_EMPTY(CONFIG_C) // 0 IS_1(CONFIG_A) // 0 IS_1(CONFIG_B) // 1 IS_1(CONFIG_C) // 0 IS_EMPTY_OR_1(CONFIG_A) // 1 IS_EMPTY_OR_1(CONFIG_B) // 1 IS_EMPTY_OR_1(CONFIG_C) // 0 In other words, they are for testing simply flags. Valid input is either 0 or 1, or a macro expansion that results in 0 or 1 or nothing. Nothing else is even supposed to work. But, as I said above, these are not library interfaces. You can use them, but make sure that you use them correctly. Regarding emptiness detection in general, it can't be done without well-defined semantics for token-pasting arbitrary tokens (i.e. where the result is not a single valid preprocessing token). With variadics and placemarkers (i.e. C99 facilities) you can get awfully close--the contraint is that you cannot have a function-like macro name as the end of the input--but that is as close as you can get. Regards, Paul Mensonides

Thank you for the explanation. Paul Mensonides wrote:
Using the BOOST_PP_IS_EMPTY macro with string literal as parameter causes compiler warning: warning: pasting "BOOST_PP_IS_EMPTY_DEF_" and ""AA"" does not give a valid preprocessing token
That macro is 1) not a library interface (so why are you using it?)
I'm using it because I was looking for something to detect emptiness and have found a macro in the preprocessor library. I can tell you what makes me thinking that this is a public macro - it's name, which follows the same convention as all the other macros' names in the library. and 2) is
not a general purpose emptiness detector (there is no such thing). There are very specific constraints on what the input is supposed to be. Now I understood that my impression was wrong. May be it makes sense to have different prefix for private macros?
Cheers, Sergei

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Serguei KOLOS
That macro is 1) not a library interface (so why are you using it?)
I'm using it because I was looking for something to detect emptiness and have found a macro in the preprocessor library. I can tell you what makes me thinking that this is a public macro - it's name, which follows the same convention as all the other macros' names in the library.
and 2) is
not a general purpose emptiness detector (there is no such thing). There are very specific constraints on what the input is supposed to be. Now I understood that my impression was wrong.
I believe that I originally intended those to be client interfaces. I added them because someone wanted them, but I didn't document them (presumably because they aren't that useful or general). With variadics, about the best you can do is in this regard is placing a constraint on the input that requires the input not to end in a function-like macro name. Chaos (when variadics are enabled) has a IS_EMPTY_NON_FUNCTION macro which provides general purpose emptiness detection except for that input constraint. Without variadics (and placemarkers), the input has such severe constraints as to make any such macro non-general purpose. I.e. it is highly specific to the types of input that you need to use it with. For now, C++ doesn't have variadics and placemarkers, so I can't add the first one to the Boost Preprocessor library. The second is not general purpose enough to be added. I wish that I could add something like this, but without variadics and placemarkers, the result is always severely crippled. (Trust me, I've tried all sorts of ways to do this from all sorts of angles. It cannot be done without severely restricting input.) With variadics, the result is only slightly crippled (i.e. it is still generally usable).
May be it makes sense to have different prefix for private macros?
Hmm. In Chaos, I use the CHAOS_PP_ prefix for interface macros and the CHAOS_IP_ prefix for implementation macros. However, there are really three types of macros--client (external) interface macros, internal interface macros, and implementation macros. I use CHAOS_PP_ for both external and internal interfaces. In Boost, any given library is (by convention) given a namespace and a macro prefix. E.g. for some library xyz, you'd get boost::xyz and BOOST_XYZ_. The BOOST_PREPROCESSOR_ prefix was shortened to BOOST_PP_ (by consensus). So, what I'd have to do, without special dispensation to break the convention, is use a secondary prefix (such as BOOST_PP_IMPL_). Regards, Paul Mensonides

Paul Mensonides wrote:
For now, C++ doesn't have variadics and placemarkers, so I can't add the first one to the Boost Preprocessor library.
I believe they are present in the current working draught for C++0x though, so you could add 'experimental' support with a C++0x feature detection macro, if you were feeling adventurous ;?) -- AlisdairM

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of AlisdairM
Paul Mensonides wrote:
For now, C++ doesn't have variadics and placemarkers, so I can't add the first one to the Boost Preprocessor library.
I believe they are present in the current working draught for C++0x though, so you could add 'experimental' support with a C++0x feature detection macro, if you were feeling adventurous ;?)
Well, such a thing would could be categorized as a "technological preview". If I was going to do that, I'd add Chaos to Boost--though I don't know if Boost is even interested in that (and even if it is, there are several policy issues that would have to be addressed). Regarding future variadic support in the pp-lib... There are a lot of things that have to change to do this correctly--most of them involve changing argument orders to best take advantage of variadics (and that is a significant change). Regarding emptiness detection... This is how Chaos does it (in case anyone is interested)... #define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__) #define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__ #define IIF(bit) PRIMITIVE_CAT(IIF_, bit) #define IIF_0(t, ...) __VA_ARGS__ #define IIF_1(t, ...) t #define SPLIT(i, ...) PRIMITIVE_CAT(SPLIT_, i)(__VA_ARGS__) #define SPLIT_0(a, ...) a #define SPLIT_1(a, ...) __VA_ARGS__ #define IS_VARIADIC(...) \ SPLIT(0, CAT(IS_VARIADIC_R_, IS_VARIADIC_C __VA_ARGS__)) \ /**/ #define IS_VARIADIC_C(...) 1 #define IS_VARIADIC_R_1 1, #define IS_VARIADIC_R_IS_VARIADIC_C 0, #define IS_EMPTY_NON_FUNCTION(...) \ IIF(IS_VARIADIC(__VA_ARGS__))( \ 0, \ IS_VARIADIC(IS_EMPTY_NON_FUNCTION_C __VA_ARGS__ ()) \ ) \ /**/ #define IS_EMPTY_NON_FUNCTION_C() () This will detect all emptiness except that it will fail if the input ends with a function-like macro name, such as: #define A() 123 IS_VARIADIC(A) This sort of thing will either error, or yield unpredictable results. Regards, Paul Mensonides
participants (3)
-
AlisdairM
-
Paul Mensonides
-
Serguei KOLOS