On 3/24/2016 4:42 AM, Florian Lindner wrote:
On Wed, 23 Mar 2016 11:56:25 -0400 Edward Diener
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 ?
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>.