Boost logo

Boost Users :

Subject: Re: [Boost-users] Looping through variadic macro arguments
From: Edward Diener (eldiener_at_[hidden])
Date: 2016-03-29 09:32:54


On 3/29/2016 6:49 AM, Florian Lindner wrote:
>
>
> 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?

Yes, of course. My error ( wipes egg off face ).

> 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.

OK. I rarely use the alphabetic alternatives to the logical operators.

>
>>
>>> 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.

Sure.

There are some really neat things you can do using the preprocessor
using Boost PP, and Boost VMD extends that realm when variadic
parameters are available, as they are for all modern compilers.

Both libraries are aids for more complicated C++ macro writing than normal.


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