[preprocessor] [variadic] BOOST_PP_VARIADICS vs BOOST_NO_VARIADIC_MACROS

Hello all, Why does Boost.Preprocessor redefines BOOST_PP_VARIAIDCS instead of just using BOOST_NO_VARIADIC_MACROS from Boost.Config? Furthermore, GCC supports variadics also when C++11 extensions are not enabled so I think the following should not && __GXX_EXPERIMENTAL_CXX0X__: // File: boost/preprocessor/config/config.hpp # /* Wave (C/C++), GCC (C++) */ # elif defined __WAVE__ && __WAVE_HAS_VARIADICS__ || defined __GNUC__ && __GXX_EXPERIMENTAL_CXX0X__ # define BOOST_PP_VARIADICS 1 Thanks. --Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/boost-preprocessor-variadic-BOOST-PP-VARI... Sent from the Boost - Dev mailing list archive at Nabble.com.

On Sat, 17 Dec 2011 12:45:26 -0800, lcaminiti wrote:
Hello all,
Why does Boost.Preprocessor redefines BOOST_PP_VARIAIDCS instead of just using BOOST_NO_VARIADIC_MACROS from Boost.Config?
The pp-lib requires more than just superficial variadic macro support. I.e. BOOST_PP_VARIADICS macro is stronger.
Furthermore, GCC supports variadics also when C++11 extensions are not enabled so I think the following should not && __GXX_EXPERIMENTAL_CXX0X__:
// File: boost/preprocessor/config/config.hpp # /* Wave (C/C++), GCC (C++) */ # elif defined __WAVE__ && __WAVE_HAS_VARIADICS__ || defined __GNUC__ && __GXX_EXPERIMENTAL_CXX0X__ # define BOOST_PP_VARIADICS 1
Because it isn't standard C++98. It can be enabled via a command line definition of BOOST_PP_VARIADICS. It is enabled by default (on GCC) when in C++11 mode. I believe that GCC 4.7 actually finally defines __cplusplus correctly as well. -Paul

On Sun, Dec 18, 2011 at 10:18 AM, Paul Mensonides <pmenso57@comcast.net> wrote:
On Sat, 17 Dec 2011 12:45:26 -0800, lcaminiti wrote:
Why does Boost.Preprocessor redefines BOOST_PP_VARIAIDCS instead of just using BOOST_NO_VARIADIC_MACROS from Boost.Config?
The pp-lib requires more than just superficial variadic macro support. I.e. BOOST_PP_VARIADICS macro is stronger.
Furthermore, GCC supports variadics also when C++11 extensions are not enabled so I think the following should not && __GXX_EXPERIMENTAL_CXX0X__:
// File: boost/preprocessor/config/config.hpp # /* Wave (C/C++), GCC (C++) */ # elif defined __WAVE__ && __WAVE_HAS_VARIADICS__ || defined __GNUC__ && __GXX_EXPERIMENTAL_CXX0X__ # define BOOST_PP_VARIADICS 1
Because it isn't standard C++98. It can be enabled via a command line definition of BOOST_PP_VARIADICS. It is enabled by default (on GCC) when in C++11 mode. I believe that GCC 4.7 actually finally defines __cplusplus correctly as well.
It is annoying to manually -DBOOST_PP_VARIADICS. That is especially true for libraries like Boost.ScopeExit and Boost.Closure that use variadics in their public APIs so the end user is required to manually define BOOST_PP_VARIADICS when Boost.Preprocessor does not automatically detect it... (e.g., on GCC 4.5.3 without -std=c++0x). Can we define what "extra" features are required by BOOST_PP_VARIADICS so I can write tests and run them to the Boost compilers and then refine the definition of BOOST_PP_VARIADICS to automatically detect all compilers where Boost.Preprocessor variadic support work. Thanks a lot. --Lorenzo

On 1/14/2012 5:42 AM, Lorenzo Caminiti wrote:
On Sun, Dec 18, 2011 at 10:18 AM, Paul Mensonides<pmenso57@comcast.net> wrote:
On Sat, 17 Dec 2011 12:45:26 -0800, lcaminiti wrote:
Why does Boost.Preprocessor redefines BOOST_PP_VARIAIDCS instead of just using BOOST_NO_VARIADIC_MACROS from Boost.Config?
The pp-lib requires more than just superficial variadic macro support. I.e. BOOST_PP_VARIADICS macro is stronger.
Furthermore, GCC supports variadics also when C++11 extensions are not enabled so I think the following should not&& __GXX_EXPERIMENTAL_CXX0X__:
// File: boost/preprocessor/config/config.hpp # /* Wave (C/C++), GCC (C++) */ # elif defined __WAVE__&& __WAVE_HAS_VARIADICS__ || defined __GNUC__ && __GXX_EXPERIMENTAL_CXX0X__ # define BOOST_PP_VARIADICS 1
Because it isn't standard C++98. It can be enabled via a command line definition of BOOST_PP_VARIADICS. It is enabled by default (on GCC) when in C++11 mode. I believe that GCC 4.7 actually finally defines __cplusplus correctly as well.
It is annoying to manually -DBOOST_PP_VARIADICS. That is especially true for libraries like Boost.ScopeExit and Boost.Closure that use variadics in their public APIs so the end user is required to manually define BOOST_PP_VARIADICS when Boost.Preprocessor does not automatically detect it... (e.g., on GCC 4.5.3 without -std=c++0x).
You can just add: #define BOOST_PP_VARIADICS in your header files before using Boost PP headers. That isn't really that annoying to do if you want to force it.
Can we define what "extra" features are required by BOOST_PP_VARIADICS so I can write tests and run them to the Boost compilers and then refine the definition of BOOST_PP_VARIADICS to automatically detect all compilers where Boost.Preprocessor variadic support work.
Look at preprocessor/config/config.h for the internal logic for defining BOOST_PP_VARIADICS.

Edward Diener-3 wrote
On 1/14/2012 5:42 AM, Lorenzo Caminiti wrote:
On Sun, Dec 18, 2011 at 10:18 AM, Paul Mensonides<pmenso57@> wrote:
On Sat, 17 Dec 2011 12:45:26 -0800, lcaminiti wrote:
Why does Boost.Preprocessor redefines BOOST_PP_VARIAIDCS instead of just using BOOST_NO_VARIADIC_MACROS from Boost.Config?
The pp-lib requires more than just superficial variadic macro support. I.e. BOOST_PP_VARIADICS macro is stronger.
Furthermore, GCC supports variadics also when C++11 extensions are not enabled so I think the following should not&& __GXX_EXPERIMENTAL_CXX0X__:
// File: boost/preprocessor/config/config.hpp # /* Wave (C/C++), GCC (C++) */ # elif defined __WAVE__&& __WAVE_HAS_VARIADICS__ || defined __GNUC__ && __GXX_EXPERIMENTAL_CXX0X__ # define BOOST_PP_VARIADICS 1
Because it isn't standard C++98. It can be enabled via a command line definition of BOOST_PP_VARIADICS. It is enabled by default (on GCC) when in C++11 mode. I believe that GCC 4.7 actually finally defines __cplusplus correctly as well.
It is annoying to manually -DBOOST_PP_VARIADICS. That is especially true for libraries like Boost.ScopeExit and Boost.Closure that use variadics in their public APIs so the end user is required to manually define BOOST_PP_VARIADICS when Boost.Preprocessor does not automatically detect it... (e.g., on GCC 4.5.3 without -std=c++0x).
You can just add:
#define BOOST_PP_VARIADICS
in your header files before using Boost PP headers. That isn't really that annoying to do if you want to force it.
Yes, in scope_exit.hpp, I could do: #include <config.hpp> #ifndef BOOST_NO_VARIADIC_MACROS #define BOOST_PP_NO_VARIADICS #endif #include <boost/preprocessor/variadic/size.hpp> ... But that way ScopeExit will make BOOST_PP_VARIADICS equivalent to BOOST_NO_VARIADIC_MACROS... that seems bad practice... then why having two macros in the first place? The story is different if the forced definition of BOOST_PP_VARIADICS is left to the end user- the user is hen on his own in overriding the default detection of the Boost.Preprocessor configuration. However, that adds extra configuration effort on the user side so Boost.Preprocessor should be as accurate as possible in defining BOOST_PP_VARIADICS on all compilers that actually support Boost.Preprocessor variadics.
Can we define what "extra" features are required by BOOST_PP_VARIADICS so I can write tests and run them to the Boost compilers and then refine the definition of BOOST_PP_VARIADICS to automatically detect all compilers where Boost.Preprocessor variadic support work.
Look at preprocessor/config/config.h for the internal logic for defining BOOST_PP_VARIADICS.
Yes, I found that logic (see below). But I was asking for exactly why this logic needs to be more conservative than BOOST_NO_VARIADIC_MACROS? In other words, what are the actual pp features that are required to define BOOST_PP_VARIADICS but not to define BOOST_NO_VARIADIC_MACROS. GCC 4.5.x without -std=c++0x is a good example. Why is BOOST_PP_VARIADICS not automatically defined for this compiler? What are the specific issuers? I was able to use at least VARIADIC_SIZE and VARIADIC_TO_SEQ on that compiler without any issue at all... # /* BOOST_PP_VARIADICS */ # # if !defined BOOST_PP_VARIADICS # /* variadic support explicitly disabled for all untested compilers */ # if defined __GCCXML__ || defined __CUDACC__ || defined __PATHSCALE__ || defined __clang__ || defined __DMC__ || defined __CODEGEARC__ || defined __BORLANDC__ || defined __MWERKS__ || defined __SUNPRO_CC || defined __HP_aCC && !defined __EDG__ || defined __MRC__ || defined __SC__ || defined __IBMCPP__ || defined __PGI # define BOOST_PP_VARIADICS 0 # /* VC++ (C/C++) */ # elif defined _MSC_VER && _MSC_VER >= 1400 && !defined __EDG__ # if _MSC_VER >= 1400 # define BOOST_PP_VARIADICS 1 # define BOOST_PP_VARIADICS_MSVC 1 # else # define BOOST_PP_VARIADICS 0 # endif # /* Wave (C/C++), GCC (C++) */ # elif defined __WAVE__ && __WAVE_HAS_VARIADICS__ || defined __GNUC__ && __GXX_EXPERIMENTAL_CXX0X__ # define BOOST_PP_VARIADICS 1 # /* EDG-based (C/C++), GCC (C), and unknown (C/C++) */ # elif !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus
= 201103L # define BOOST_PP_VARIADICS 1 # else # define BOOST_PP_VARIADICS 0 # endif # elif !BOOST_PP_VARIADICS + 1 < 2 # undef BOOST_PP_VARIADICS # define BOOST_PP_VARIADICS 1 # if defined _MSC_VER && _MSC_VER >= 1400 && !(defined __EDG__ || defined __GCCXML__ || defined __CUDACC__ || defined __PATHSCALE__ || defined __clang__ || defined __DMC__ || defined __CODEGEARC__ || defined __BORLANDC__ || defined __MWERKS__ || defined __SUNPRO_CC || defined __HP_aCC || defined __MRC__ || defined __SC__ || defined __IBMCPP__ || defined __PGI) # define BOOST_PP_VARIADICS_MSVC 1 # endif # else # undef BOOST_PP_VARIADICS # define BOOST_PP_VARIADICS 0 # endif
Edward, thanks again for providing the variadic support which I found very useful in all my libraries. --Lorenzo -- View this message in context: http://boost.2283326.n4.nabble.com/boost-preprocessor-variadic-BOOST-PP-VARI... Sent from the Boost - Dev mailing list archive at Nabble.com.

On 1/14/2012 9:07 AM, lcaminiti wrote:
Edward Diener-3 wrote
On 1/14/2012 5:42 AM, Lorenzo Caminiti wrote:
On Sun, Dec 18, 2011 at 10:18 AM, Paul Mensonides<pmenso57@> wrote:
On Sat, 17 Dec 2011 12:45:26 -0800, lcaminiti wrote:
Why does Boost.Preprocessor redefines BOOST_PP_VARIAIDCS instead of just using BOOST_NO_VARIADIC_MACROS from Boost.Config?
The pp-lib requires more than just superficial variadic macro support. I.e. BOOST_PP_VARIADICS macro is stronger.
Furthermore, GCC supports variadics also when C++11 extensions are not enabled so I think the following should not&& __GXX_EXPERIMENTAL_CXX0X__:
// File: boost/preprocessor/config/config.hpp # /* Wave (C/C++), GCC (C++) */ # elif defined __WAVE__&& __WAVE_HAS_VARIADICS__ || defined __GNUC__ && __GXX_EXPERIMENTAL_CXX0X__ # define BOOST_PP_VARIADICS 1
Because it isn't standard C++98. It can be enabled via a command line definition of BOOST_PP_VARIADICS. It is enabled by default (on GCC) when in C++11 mode. I believe that GCC 4.7 actually finally defines __cplusplus correctly as well.
It is annoying to manually -DBOOST_PP_VARIADICS. That is especially true for libraries like Boost.ScopeExit and Boost.Closure that use variadics in their public APIs so the end user is required to manually define BOOST_PP_VARIADICS when Boost.Preprocessor does not automatically detect it... (e.g., on GCC 4.5.3 without -std=c++0x).
You can just add:
#define BOOST_PP_VARIADICS
in your header files before using Boost PP headers. That isn't really that annoying to do if you want to force it.
Yes, in scope_exit.hpp, I could do:
#include<config.hpp> #ifndef BOOST_NO_VARIADIC_MACROS #define BOOST_PP_NO_VARIADICS #endif #include<boost/preprocessor/variadic/size.hpp> ...
But that way ScopeExit will make BOOST_PP_VARIADICS equivalent to BOOST_NO_VARIADIC_MACROS... that seems bad practice... then why having two macros in the first place?
This was Paul's decision. My original plan was to use BOOS_NO_VARIADIC_MACROS but he was pretty adamant that he did not want any warnings from Boost PP and he wanted C99/C++0x-like support for variadic macros, so he made it more restrictive for Boost PP.
The story is different if the forced definition of BOOST_PP_VARIADICS is left to the end user- the user is hen on his own in overriding the default detection of the Boost.Preprocessor configuration. However, that adds extra configuration effort on the user side so Boost.Preprocessor should be as accurate as possible in defining BOOST_PP_VARIADICS on all compilers that actually support Boost.Preprocessor variadics.
Can we define what "extra" features are required by BOOST_PP_VARIADICS so I can write tests and run them to the Boost compilers and then refine the definition of BOOST_PP_VARIADICS to automatically detect all compilers where Boost.Preprocessor variadic support work.
Look at preprocessor/config/config.h for the internal logic for defining BOOST_PP_VARIADICS.
Yes, I found that logic (see below). But I was asking for exactly why this logic needs to be more conservative than BOOST_NO_VARIADIC_MACROS? In other words, what are the actual pp features that are required to define BOOST_PP_VARIADICS but not to define BOOST_NO_VARIADIC_MACROS.
You will have to argue with Paul.
GCC 4.5.x without -std=c++0x is a good example. Why is BOOST_PP_VARIADICS not automatically defined for this compiler? What are the specific issuers? I was able to use at least VARIADIC_SIZE and VARIADIC_TO_SEQ on that compiler without any issue at all...
# /* BOOST_PP_VARIADICS */ # # if !defined BOOST_PP_VARIADICS # /* variadic support explicitly disabled for all untested compilers */ # if defined __GCCXML__ || defined __CUDACC__ || defined __PATHSCALE__ || defined __clang__ || defined __DMC__ || defined __CODEGEARC__ || defined __BORLANDC__ || defined __MWERKS__ || defined __SUNPRO_CC || defined __HP_aCC&& !defined __EDG__ || defined __MRC__ || defined __SC__ || defined __IBMCPP__ || defined __PGI # define BOOST_PP_VARIADICS 0 # /* VC++ (C/C++) */ # elif defined _MSC_VER&& _MSC_VER>= 1400&& !defined __EDG__ # if _MSC_VER>= 1400 # define BOOST_PP_VARIADICS 1 # define BOOST_PP_VARIADICS_MSVC 1 # else # define BOOST_PP_VARIADICS 0 # endif # /* Wave (C/C++), GCC (C++) */ # elif defined __WAVE__&& __WAVE_HAS_VARIADICS__ || defined __GNUC__&& __GXX_EXPERIMENTAL_CXX0X__ # define BOOST_PP_VARIADICS 1 # /* EDG-based (C/C++), GCC (C), and unknown (C/C++) */ # elif !defined __cplusplus&& __STDC_VERSION__>= 199901L || __cplusplus
= 201103L # define BOOST_PP_VARIADICS 1 # else # define BOOST_PP_VARIADICS 0 # endif # elif !BOOST_PP_VARIADICS + 1< 2 # undef BOOST_PP_VARIADICS # define BOOST_PP_VARIADICS 1 # if defined _MSC_VER&& _MSC_VER>= 1400&& !(defined __EDG__ || defined __GCCXML__ || defined __CUDACC__ || defined __PATHSCALE__ || defined __clang__ || defined __DMC__ || defined __CODEGEARC__ || defined __BORLANDC__ || defined __MWERKS__ || defined __SUNPRO_CC || defined __HP_aCC || defined __MRC__ || defined __SC__ || defined __IBMCPP__ || defined __PGI) # define BOOST_PP_VARIADICS_MSVC 1 # endif # else # undef BOOST_PP_VARIADICS # define BOOST_PP_VARIADICS 0 # endif
Edward, thanks again for providing the variadic support which I found very useful in all my libraries.
You are very welcome. It was a labor of love, especially when one has to deal with VC++ and its preprocessor headaches, also in my extra VMD functionality.

On Sat, 14 Jan 2012 06:07:13 -0800, lcaminiti wrote:
You can just add:
#define BOOST_PP_VARIADICS
in your header files before using Boost PP headers. That isn't really that annoying to do if you want to force it.
Yes, in scope_exit.hpp, I could do:
#include <config.hpp> #ifndef BOOST_NO_VARIADIC_MACROS #define BOOST_PP_NO_VARIADICS #endif #include <boost/preprocessor/variadic/size.hpp> ...
But that won't actually work in the real world as it depends on the order of inclusion.
But that way ScopeExit will make BOOST_PP_VARIADICS equivalent to BOOST_NO_VARIADIC_MACROS... that seems bad practice... then why having two macros in the first place?
As I said before, BOOST_PP_VARIADICS is a stronger requirement on the preprocessor than !BOOST_NO_VARIADIC_MACROS. The reason is that it isn't simply a flag that determines whether the preprocessor supports variadic macros (superficially or otherwise). Instead, it enables a set of functionality in the pp-lib that is highly dependent on the details of the behavior of the preprocessor itself. This would be a non-issue if preprocessors all actually conformed to respective standards, but they don't. Because of that, the implementation is highly tuned for each preprocessor known to work.
The story is different if the forced definition of BOOST_PP_VARIADICS is left to the end user- the user is hen on his own in overriding the default detection of the Boost.Preprocessor configuration. However, that adds extra configuration effort on the user side so Boost.Preprocessor should be as accurate as possible in defining BOOST_PP_VARIADICS on all compilers that actually support Boost.Preprocessor variadics.
Variadic macros are a >= C99 and >= C++11 feature. They are not part of the C++98 language, and thus they are not enabled by default on GCC when GCC is not compiling those languages. Variadic macros enabled in C++98 are a compiler extension. If you want to force it, you can, but the pp- lib is not going to use compiler extensions by default.
Can we define what "extra" features are required by BOOST_PP_VARIADICS so I can write tests and run them to the Boost compilers and then refine the definition of BOOST_PP_VARIADICS to automatically detect all compilers where Boost.Preprocessor variadic support work.
It isn't that simple, though some preprocessors are worse than others. It isn't an exact feature set so much as it is attempting to understand the behavior of complex macro expansion algorithms used in any given preprocessor with only the results of the algorithms rather than the algorithms themselves. What works in one particular use case suddenly fails in another for no apparent reason. The problem is that our understanding of the behavior of the particular preprocessor is only approximate, and that approximation deviates in a combinatorial fashion (i.e. when you use interface A everything works, when you use interface B everything works, but when you use both A and B it fails). This type of behavior is particularly apparent with VC++ as Edward can attest to, and both Edward and I spent a significant amount of time stabilizing the library on VC++ because it is such a popular compiler. That said, Boost is used on a lot of different compilers. The pp-lib specifically is used heavily throughout Boost either directly or indirectly. The majority of Boost users don't use the pp-lib directly just as they often don't use the MPL directly. Because of that, it is more important that the libraries most commonly used in Boost are stable, and that is why the pp-lib has to be what you probably consider to be overly conservative.
Look at preprocessor/config/config.h for the internal logic for defining BOOST_PP_VARIADICS.
Yes, I found that logic (see below). But I was asking for exactly why this logic needs to be more conservative than BOOST_NO_VARIADIC_MACROS? In other words, what are the actual pp features that are required to define BOOST_PP_VARIADICS but not to define BOOST_NO_VARIADIC_MACROS.
GCC 4.5.x without -std=c++0x is a good example. Why is BOOST_PP_VARIADICS not automatically defined for this compiler? What are the specific issuers? I was able to use at least VARIADIC_SIZE and VARIADIC_TO_SEQ on that compiler without any issue at all...
Because C++98 doesn't have variadic macros. You want variadic macros, use a C++0x/C++11 compiler or use the backdoor already provided (the command line definition of BOOST_PP_VARIADICS). Regards, Paul Mensonides
participants (4)
-
Edward Diener
-
lcaminiti
-
Lorenzo Caminiti
-
Paul Mensonides