Boost logo

Boost Users :

Subject: Re: [Boost-users] Looping through variadic macro arguments
From: Florian Lindner (mailinglists_at_[hidden])
Date: 2016-03-23 11:45:17


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?

Thanks a lot!
Florian

The code looks like that:

#define PRINT_ARGUMENT(r, data, i, elem) \
  std::cerr << " Argument " << i << ": " << elem << std::endl;

#define assertion(expr, ...) if (!(expr)) { \
    std::cerr << "Assertion in " << __FILE__ << ":" << __LINE__ \
              << ", failed expression: " << #expr << std::endl; \
    std::cout << BOOST_PP_VARIADIC_SIZE(__VA_ARGS__) << std::endl; \
    BOOST_PP_SEQ_FOR_EACH_I(PRINT_ARGUMENT,, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)); \
    std::cerr.flush(); \
    std::cout.flush(); \
    assert(false); \
  } \
  

On Tue, 22 Mar 2016 20:53:06 -0400
Edward Diener <eldiener_at_[hidden]> wrote:

> On 3/22/2016 3:35 PM, Florian Lindner wrote:
> > On Mon, 21 Mar 2016 10:39:52 -0400
> > Edward Diener <eldiener_at_[hidden]> wrote:
> >
> >> On 3/21/2016 4:55 AM, Florian Lindner wrote:
> >>> Hey,
> >>>
> >> snipped ...
> >>>
> > [...]
> >>>
> >>>
> >>> Any comments on that? How to do it better? Maybe without a helper
> >>> macro PRINT?
> >>> I'm a bit surprised I have to use r-1 to get 1 for the first
> >>> argument.
> >>
> >> The PRINT macro is fine. Almost all Boost PP looping constructs
> >> use a helper macro like that.
> >>
> >> In real life code I would name all macros in uppercase and give
> >> them a very distinct name to reduce clashes with other potential
> >> C++ identifiers and macros.
> >
> > Sure!
> >
> >> Look at BOOST_PP_SEQ_FOR_EACH_I to get the actual argument index
> >> instead of using 'r'.
> >>
> >> That 'r' in your code above is actually 2,3, and 4 is just luck.
> >> The 'next available BOOST_PP_FOR repetition' as described in the
> >> doc just happened to be 2,3, and 4 but could theoretically have
> >> been any PP number each time and is not related to the index of
> >> each argument.
> >
> > Ok, try to use FOR_EACH_I, but ran into compilation errors:
> >
> > #define PRINT(r, data, i, elem) \
> > cout << "Argument " << i << ": " << elem << endl;
> >
> > #define
> > vmacro(expr, ...) \
> > cout << "Expression: " << #expr <<
> > endl; \
> > BOOST_PP_SEQ_FOR_EACH_I(PRINT, ,
> > BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)); \
>
> What is that final '\' about ?
>
> Please show the header files being included.
>
> >
> >
> > but:
> >
> > % g++ -std=c++11 -g3 -rdynamic -ldl test.cpp
> > && ./a.out :( test.cpp:
> > In function 'void f(int)': test.cpp:127:27: error: 'PRINT' was not
> > declared in this scope BOOST_PP_SEQ_FOR_EACH_I(PRINT, ,
> > BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)); \ ^
> > test.cpp:159:3: note: in expansion of macro 'vmacro'
> > vmacro(1-2, 5, 6);
> > ^
> > test.cpp:127:34: error: expected primary-expression before ',' token
> > BOOST_PP_SEQ_FOR_EACH_I(PRINT, ,
> > BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)); \ ^
> > test.cpp:159:3: note: in expansion of macro 'vmacro'
> > vmacro(1-2, 5, 6);
> > ^
> > In file included
> > from /usr/include/boost/preprocessor/variadic/to_seq.hpp:17:0, from
> > test.cpp:11: test.cpp:127:36: error: expression cannot be used as a
> > function BOOST_PP_SEQ_FOR_EACH_I(PRINT, ,
> > BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)); \ ^
> > test.cpp:159:3: note: in expansion of macro 'vmacro'
> > vmacro(1-2, 5, 6);
> > ^
> > test.cpp:127:73: error: 'BOOST_PP_SEQ_FOR_EACH_I' was not declared
> > in this scope BOOST_PP_SEQ_FOR_EACH_I(PRINT, ,
> > BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)); \ ^
> > test.cpp:159:3: note: in expansion of macro 'vmacro'
> > vmacro(1-2, 5, 6);
> > ^
> >
> >
> > boost 1.60, gcc 5.3.0.
> >
> > The same code, using FOR_EACH works (only the argumentens of PRINT
> > were altered.
> >
> > 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