Hey,
I have integrated the code in our project now and it fails to compile
with some older clang version.
It compiles fine with clang++ 3.7.1 and g++ 5.3.0 on my arch machine as
well as g++ 4.8.4 on our ubuntu server, but fails with clang++ 3.4 on
this machine as well as the travis
The complete compiler messages are at http://pastebin.com/HgjgCfsH it
is mostly something like that:
error: unknown type name 'BOOST_PP_IIF_0'
assertion( reinterpret_cast
On 3/29/2016 6:49 AM, Florian Lindner wrote:
On Thu, 24 Mar 2016 11:00:57 -0400 Edward Diener
wrote: 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 ?
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.