Boost logo

Boost Users :

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


Hey,

On Fri, 18 Mar 2016 09:06:26 -0400
Edward Diener <eldiener_at_[hidden]> wrote:

> On 3/18/2016 6:19 AM, Florian Lindner wrote:
> > Hello,
> >
> > I have this macro:
> >
> > #define
> > vmacro(expr, ...) \
> > cout << "n macro = " << BOOST_PP_VARIADIC_SIZE(__VA_ARGS__) <<
> > endl; \ cout << BOOST_PP_VARIADIC_ELEM(0, __VA_ARGS__) <<
> > endl; \ cout << BOOST_PP_VARIADIC_ELEM(1,
> > __VA_ARGS__) << endl; \ for (int i = 0; i <
> > BOOST_PP_VARIADIC_SIZE(__VA_ARGS__); i++) { \ cout << i << ":
> > " << BOOST_PP_VARIADIC_ELEM(i, __VA_ARGS__) << endl; \ }
> >
> > The VARIADIC_SIZE is correct and I can access elements using
> > BOOST_PP_VARIADIC_ELEM as long as I use a literal. The loop body
> > produces error messages when compiling. BOOST_PP_VARIADICS is 1.
>
> Your macro 'vmacro' gets expanded at preprocessor time when it is
> invoked as 'vmacro(4,5,6)'. At preprocessor time the expansion of
> 'BOOST_PP_VARIADIC_ELEM(i, __VA_ARGS__)' fails because 'i' is not a
> valid Boost PP number.

Thanks for your explanation!

> > The goal is to concatenate all variadic macro arguments to a
> > string. If there a more clever solution, I'm very eager to hear
> > them.
>
> #include <boost/preprocessor/stringize.hpp>
> #include <boost/preprocessor/seq/cat.hpp>
> #include <boost/preprocessor/variadic/to_seq.hpp>
>
> cout <<
> BOOST_PP_STRINGIZE(BOOST_PP_SEQ_CAT(BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)))
> << endl;

I also want to write some text between the sequence items, I have made
it working with that code:

#define PRINT(r, data, elem) \
  cout << "Argument " << r-1 << ": " << elem << endl;

#define vmacro(expr, ...) \
  cout << "Expression: " << #expr << endl; \
  BOOST_PP_SEQ_FOR_EACH(PRINT, ,
  BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)); \

So, invoking vmacro(1-2, 5, 6, "Hallo"); prints

#define PRINT(r, data, elem) \
  cout << "Argument " << r-1 << ": " << elem << endl;

#define vmacro(expr, ...)
\ cout << "Expression: " << #expr << endl; \
  BOOST_PP_SEQ_FOR_EACH(PRINT, ,
BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)); \

Expression: 1-2
Argument 1: 5
Argument 2: 6
Argument 3: Hallo

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.

Best,
Florian

> >
> > Thanks!
> > Florian
> >
> >
> > ERROR MESSAGES:
> >
> > % clang++ -std=c++11 -g3 -rdynamic -ldl test.cpp
> > test.cpp:154:3: error: expected expression
> > vmacro(4, 5, 6);
> > ^
> > test.cpp:120:26: note: expanded from macro 'vmacro'
> > cout << i << ": " << BOOST_PP_VARIADIC_ELEM(i, __VA_ARGS__) <<
> > endl; \ ^
> > /usr/include/boost/preprocessor/variadic/elem.hpp:26:101: note:
> > expanded from macro 'BOOST_PP_VARIADIC_ELEM' # define
> > BOOST_PP_VARIADIC_ELEM(n, ...)
> > BOOST_PP_CAT(BOOST_PP_VARIADIC_ELEM_, n)(__VA_ARGS__,) ^ 1 error
> > generated.
> >
> >
> > g++ -std=c++11 -g3 -rdynamic -ldl test.cpp
> > In file included from test.cpp:9:0:
> > test.cpp: In function 'void f(int)':
> > test.cpp:120:26: error: expected primary-expression before ')' token
> > cout << i << ": " << BOOST_PP_VARIADIC_ELEM(i, __VA_ARGS__)
> > << endl; \ ^
> > test.cpp:154:3: note: in expansion of macro 'vmacro'
> > vmacro(4, 5, 6);
> > ^
> > test.cpp:120:26: error: 'BOOST_PP_VARIADIC_ELEM_i' was not declared
> > in this scope cout << i << ": " << BOOST_PP_VARIADIC_ELEM(i,
> > __VA_ARGS__) << endl; \ ^
> > test.cpp:154:3: note: in expansion of macro 'vmacro'
> > vmacro(4, 5, 6);
> > ^
> >


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