Boost logo

Boost Users :

Subject: Re: [Boost-users] Looping through variadic macro arguments
From: Florian Lindner (mailinglists_at_[hidden])
Date: 2016-03-24 04:42:13


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:

#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__)) { \
    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?

Best Thanks,
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