Boost logo

Boost Users :

Subject: Re: [Boost-users] Looping through variadic macro arguments
From: Florian Lindner (mailinglists_at_[hidden])
Date: 2016-03-29 06:49:37


On Thu, 24 Mar 2016 11:00:57 -0400
Edward Diener <eldiener_at_[hidden]> wrote:

> On 3/24/2016 4:42 AM, Florian Lindner wrote:
> >
> >
> > On Wed, 23 Mar 2016 11:56:25 -0400
> > Edward Diener <eldiener_at_[hidden]> wrote:
> >
> >> On 3/23/2016 11:45 AM, Florian Lindner wrote:
> >>> Hello,
> >>>
> >>> another question: I was expecting that the line
> >>>
> >>> BOOST_PP_SEQ_FOR_EACH_I(PRINT_ARGUMENT,,
> >>> BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__));
> >>>
> >>> in a macro #define vm(expr, ...) expands to nothing, when the the
> >>> macro is called with just one argument vm(false), but it fails,
> >>> only when called with just one argument:
> >>>
> >>> % g++ -std=c++11 -g3 test.cpp
> >>>
> >>> test.cpp: In function 'void f(int)':
> >>> test.cpp:109:51: error: expected primary-expression before '<<'
> >>> token std::cerr << " Argument " << i << ": " << elem <<
> >>> std::endl; ^
> >>> /usr/include/boost/preprocessor/seq/for_each_i.hpp:85:66: note: in
> >>> expansion of macro 'PRINT_ARGUMENT' # define
> >>> BOOST_PP_SEQ_FOR_EACH_I_M_I(r, macro, data, seq, i, sz) macro(r,
> >>> data, i, BOOST_PP_SEQ_HEAD(seq)) ^ test.cpp:140:1: note: in
> >>> expansion of macro 'assertion' assertion(!true);
> >>> ^
> >>>
> >>>
> >>> Is there any way to make it work like that?
> >>
> >> When you specify '...' to indicate variadic arguments you must
> >> always supply at least one argument. That's part of the C++
> >> standard.
> >>
> >> The way to make 'vm' work is to specify:
> >>
> >> #define vm(...)
> >>
> >> and then extract your first argument and pass the remaining
> >> arguments, if they exist, to your BOOST_PP_SEQ_FOR_EACH_I
> >> expansion. I will let you figure out how to do that, but if you
> >> find you can't figure it out post back and I will show you the
> >> code.
> >
> > Hey,
> >
> > ok, I used SEQ_TAIL for that and it works nicely:
>
> That's the solution.
>
> I could add a BOOST_PP_VARIADIC_TAIL but keeping the Boost PP
> variadic macros to a minimum was the idea when they were created.
>
> >
> > #define PRINT_ARGUMENT(r, data, i, elem) \
> > std::cerr << " Argument " << i << ": " << elem << std::endl;
> >
> > #define assertion(...) if (not BOOST_PP_VARIADIC_ELEM(0,
> > __VA_ARGS__)) { \
>
> Wouldn't
>
> if !(BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__)) { \
>
> be better ?

The if condition needs to be enclosed by parens, don't it? This piece
of code does not compile?
Or do you propose to replace the "not" by "!"? I think they are the
same, I just like the "not" better, since it's more literal.

>
> > std::cerr << "Assertion in " << __FILE__ << ":" <<
> > __LINE__ \ << ", failed expression: " <<
> > BOOST_PP_STRINGIZE(BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__)) <<
> > std::endl; \ BOOST_PP_SEQ_FOR_EACH_I(PRINT_ARGUMENT,,
> > BOOST_PP_SEQ_TAIL(BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))); \
> > std::cerr.flush();
> > \
> > std::cout.flush();
> > \
> > assert(false);
> > \ }
> >
> > as you can see, it's going to be an asssert macro. STRINGIZE gives
> > me the literal expression, like the # operator.
> >
> > Any comments?
>
> I'm glad Boost PP is useful to you <g>. If you are further interested
> in preprocessor programming in general you might find my Boost VMD
> library interesting ( shameless plug ) <g>.

Thanks, I'll keep it in mind. But I try to keep preprocessor
programming to a minimum.

Best,
Florian


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net