[Preprocessor] MSVC nonstandard macro expansion workaround?
Hi folks,
I've been trying to get Boost.Preprocessor to run a nested for loop over
two sequences to output nested switch blocks and case statements. This
works fine with GCC and clang. Unfortunately it's broken with MSVC. If
anyone had any thoughts on what I might need to tweak to enable the code
to work with MSVC, I'd be very appreciative. Even if it's as nasty as a
big ifdef with an alternative set of macros!
This is the test case:
--------
#include
cl /EHsc /I \path\to\boost-1_60 /Fe:test-pp.exe test-pp.cpp Microsoft (R) C/C++ Optimizing Compiler Version 18.00.40629 for x64 Copyright (C) Microsoft Corporation. All rights reserved.
test-pp.cpp test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_VARIADIC_ELEM_3' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_BOOL' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_BOOL_I' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_VARIADIC_ELEM_2' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_DEC' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_DEC_I' test-pp.cpp(22) : error C2065: 'BOOST_PP_SEQ_FOR_EACH_M' : undeclared identifier test-pp.cpp(22) : error C2065: 'BOOST_PP_TUPLE_EAT_2' : undeclared identifier test-pp.cpp(22) : error C2065: 'LT_NESTED' : undeclared identifier test-pp.cpp(22) : error C2064: term does not evaluate to a function taking 1 arguments test-pp.cpp(22) : error C2146: syntax error : missing ';' before identifier 'BOOST_PP_IIF_BOOST_PP_BOOL_' test-pp.cpp(22) : error C3861: 'BOOST_PP_IIF_BOOST_PP_BOOL_': identifier not found test-pp.cpp(22) : error C2065: 'BOOST_PP_FOR_3' : undeclared identifier test-pp.cpp(22) : error C2065: 'BOOST_PP_TUPLE_EAT_4' : undeclared identifier test-pp.cpp(22) : error C2059: syntax error : ',' test-pp.cpp(22) : error C3861: 'BOOST_PP_EXPAND': identifier not found test-pp.cpp(22) : error C2065: 'BOOST_PP_FOR_4' : undeclared identifier test-pp.cpp(22) : error C2065: 'BOOST_PP_FOR_5' : undeclared identifier test-pp.cpp(22) : error C2065: 'BOOST_PP_FOR_6' : undeclared identifier test-pp.cpp(22) : error C2065: 'BOOST_PP_FOR_7' : undeclared identifier test-pp.cpp(22) : error C2065: 'BOOST_PP_FOR_8' : undeclared identifier test-pp.cpp(22) : error C2065: 'BOOST_PP_FOR_9' : undeclared identifier test-pp.cpp(22) : error C2065: 'BOOST_PP_FOR_10' : undeclared identifier I've spent hours tweaking the testcase to try to make this work, but so far without success. It doesn't help that I don't fully understand what specifically is broken with the MSVC preprocessor, or how to work around whatever is behaving in a non-stanadard way. Many thanks, Roger
On Thursday, March 3, 2016 7:50 AM, "rleigh@codelibre.net"
wrote:
Hi folks,
I've been trying to get Boost.Preprocessor to run a nested for loop over two sequences to output nested switch blocks and case statements. This works fine with GCC and clang. Unfortunately it's broken with MSVC. If anyone had any thoughts on what I might need to tweak to enable the code to work with MSVC, I'd be very appreciative. Even if it's as nasty as a
big ifdef with an alternative set of macros!
I don't have MSVC available to test this right now, but you could try adding an extra scan and avoid using strange operator combinations as well: BOOST_PP_EXPAND(BOOST_PP_EXPAND(BOOST_PP_SEQ_FOR_EACH(LT_TOPLEVEL,, LASERTYPE_VALUES))); If that doesn't work. Would you be able to post the PP output of what gets expanded inside of main? This would help diagnose the issue, until someone can look at it with MSVC.
I've spent hours tweaking the testcase to try to make this work, but so far without success. It doesn't help that I don't fully understand what
specifically is broken with the MSVC preprocessor, or how to work around
whatever is behaving in a non-stanadard way.
The MSVC preprocessor works in a mysterious way, that its difficult to understand why it fails in one situation and not the other. Paul
On 03/03/2016 19:37, paul Fultz wrote:
On Thursday, March 3, 2016 7:50 AM, "rleigh@codelibre.net"
wrote:
I've been trying to get Boost.Preprocessor to run a nested for loop over two sequences to output nested switch blocks and case statements. This works fine with GCC and clang. Unfortunately it's broken with MSVC. If anyone had any thoughts on what I might need to tweak to enable the code to work with MSVC, I'd be very appreciative. Even if it's as nasty as a
big ifdef with an alternative set of macros!
I don't have MSVC available to test this right now, but you could try adding an extra scan and avoid using strange operator combinations as well:
BOOST_PP_EXPAND(BOOST_PP_EXPAND(BOOST_PP_SEQ_FOR_EACH(LT_TOPLEVEL,, LASERTYPE_VALUES)));
If that doesn't work. Would you be able to post the PP output of what gets expanded inside of main? This would help diagnose the issue, until someone can look at it with MSVC.
With the plain source as I posted: failure to expand a whole set of macros. test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_VARIADIC_ELEM_3' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_BOOL' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_BOOL_I' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_VARIADIC_ELEM_2' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_DEC' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_DEC_I' -------- enum LaserType { EXCIMER, GAS, METALVAPOR, SOLIDSTATE, DYE, SEMICONDUCTOR, FREEELECTRON, OTHER }; int main() { std::cout << "Test toplevel: " << LaserType(EXCIMER ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(3, (LT_NESTED, EXCIMER, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_3, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, EXCIMER, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(GAS ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(4, (LT_NESTED, GAS, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_4, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, GAS, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(METALVAPOR ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(5, (LT_NESTED, METALVAPOR, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_5, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, METALVAPOR, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(SOLIDSTATE ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(6, (LT_NESTED, SOLIDSTATE, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_6, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, SOLIDSTATE, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(DYE ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(7, (LT_NESTED, DYE, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_7, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, DYE, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(SEMICONDUCTOR ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(8, (LT_NESTED, SEMICONDUCTOR, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_8, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, SEMICONDUCTOR, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(FREEELECTRON ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(9, (LT_NESTED, FREEELECTRON, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_9, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, FREEELECTRON, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(OTHER ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(10, (LT_NESTED, OTHER, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_10, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, OTHER, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); ; } -------- With the addition of another BOOST_PP_EXPAND at the top level, I get the same except for minor whitespace differences: test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_VARIADIC_ELEM_3' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_BOOL' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_BOOL_I' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_VARIADIC_ELEM_2' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_DEC' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_DEC_I' -------- enum LaserType { EXCIMER, GAS, METALVAPOR, SOLIDSTATE, DYE, SEMICONDUCTOR, FREEELECTRON, OTHER }; int main() { std::cout << "Test toplevel: " << LaserType(EXCIMER ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(3, (LT_NESTED, EXCIMER, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_3, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, EXCIMER, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(GAS ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(4, (LT_NESTED, GAS, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_4, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, GAS, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(METALVAPOR ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(5, (LT_NESTED, METALVAPOR, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_5, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, METALVAPOR, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(SOLIDSTATE ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(6, (LT_NESTED, SOLIDSTATE, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_6, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, SOLIDSTATE, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(DYE ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(7, (LT_NESTED, DYE, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_7, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, DYE, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(SEMICONDUCTOR ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(8, (LT_NESTED, SEMICONDUCTOR, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_8, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, SEMICONDUCTOR, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(FREEELECTRON ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(9, (LT_NESTED, FREEELECTRON, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_9, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, FREEELECTRON, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(OTHER ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(10, (LT_NESTED, OTHER, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_10, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, OTHER, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M);; } -------- I've tried changing the expansion in the LT_TOPLEVEL macro with variants of PP_DEFER/PP_SEQ_FOR_EACH_R/PP_EXPAND without it making any significant difference. Oh MSVC how I detest thee! Regards, Roger
On 3/4/2016 5:33 AM, Roger Leigh wrote:
On 03/03/2016 19:37, paul Fultz wrote:
On Thursday, March 3, 2016 7:50 AM, "rleigh@codelibre.net"
wrote: I've been trying to get Boost.Preprocessor to run a nested for loop over two sequences to output nested switch blocks and case statements. This works fine with GCC and clang. Unfortunately it's broken with MSVC. If anyone had any thoughts on what I might need to tweak to enable the code to work with MSVC, I'd be very appreciative. Even if it's as nasty as a
big ifdef with an alternative set of macros!
I don't have MSVC available to test this right now, but you could try adding an extra scan and avoid using strange operator combinations as well:
BOOST_PP_EXPAND(BOOST_PP_EXPAND(BOOST_PP_SEQ_FOR_EACH(LT_TOPLEVEL,, LASERTYPE_VALUES)));
If that doesn't work. Would you be able to post the PP output of what gets expanded inside of main? This would help diagnose the issue, until someone can look at it with MSVC.
With the plain source as I posted: failure to expand a whole set of macros.
test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_VARIADIC_ELEM_3' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_BOOL' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_BOOL_I' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_VARIADIC_ELEM_2' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_DEC' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_DEC_I' -------- enum LaserType { EXCIMER, GAS, METALVAPOR, SOLIDSTATE, DYE, SEMICONDUCTOR, FREEELECTRON, OTHER };
int main() { std::cout << "Test toplevel: " << LaserType(EXCIMER ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(3, (LT_NESTED, EXCIMER, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_3, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, EXCIMER, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(GAS ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(4, (LT_NESTED, GAS, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_4, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, GAS, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(METALVAPOR ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(5, (LT_NESTED, METALVAPOR, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_5, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, METALVAPOR, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(SOLIDSTATE ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(6, (LT_NESTED, SOLIDSTATE, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_6, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, SOLIDSTATE, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(DYE ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(7, (LT_NESTED, DYE, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_7, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, DYE, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(SEMICONDUCTOR ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(8, (LT_NESTED, SEMICONDUCTOR, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_8, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, SEMICONDUCTOR, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(FREEELECTRON ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(9, (LT_NESTED, FREEELECTRON, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_9, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, FREEELECTRON, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(OTHER ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(10, (LT_NESTED, OTHER, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_10, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, OTHER, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); ; } --------
With the addition of another BOOST_PP_EXPAND at the top level, I get the same except for minor whitespace differences:
test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_VARIADIC_ELEM_3' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_BOOL' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_BOOL_I' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_VARIADIC_ELEM_2' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_DEC' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_DEC_I' -------- enum LaserType { EXCIMER, GAS, METALVAPOR, SOLIDSTATE, DYE, SEMICONDUCTOR, FREEELECTRON, OTHER };
int main() { std::cout << "Test toplevel: " << LaserType(EXCIMER ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(3, (LT_NESTED, EXCIMER, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_3, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, EXCIMER, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(GAS ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(4, (LT_NESTED, GAS, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_4, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, GAS, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(METALVAPOR ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(5, (LT_NESTED, METALVAPOR, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_5, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, METALVAPOR, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(SOLIDSTATE ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(6, (LT_NESTED, SOLIDSTATE, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_6, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, SOLIDSTATE, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(DYE ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(7, (LT_NESTED, DYE, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_7, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, DYE, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(SEMICONDUCTOR ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(8, (LT_NESTED, SEMICONDUCTOR, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_8, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, SEMICONDUCTOR, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(FREEELECTRON ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(9, (LT_NESTED, FREEELECTRON, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_9, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, FREEELECTRON, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M); std::cout << "Test toplevel: " << LaserType(OTHER ) << " \n"; BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_SEQ_FOR_EACH_M, BOOST_PP_TUPLE_EAT_2)(10, (LT_NESTED, OTHER, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8)) BOOST_PP_IIF_BOOST_PP_BOOL_(BOOST_PP_FOR_10, BOOST_PP_TUPLE_EAT_4)(( BOOST_PP_EXPAND(LT_NESTED, OTHER, (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER), 8), , BOOST_PP_IIF_BOOST_PP_BOOL_BOOST_PP_DEC_(BOOST_PP_SEQ_FOR_EACH_O_I_TAIL, BOOST_PP_SEQ_FOR_EACH_O_I_NIL) (), BOOST_PP_DEC_ ), BOOST_PP_SEQ_FOR_EACH_P, BOOST_PP_SEQ_FOR_EACH_O, BOOST_PP_SEQ_FOR_EACH_M);; } --------
I've tried changing the expansion in the LT_TOPLEVEL macro with variants of PP_DEFER/PP_SEQ_FOR_EACH_R/PP_EXPAND without it making any significant difference. Oh MSVC how I detest thee!
The general problem you are encountering in the VC++ preprocessor is that it often re-scans macro expansion when it should not be doing so according to the preprocessor rules of standard C++. I give a simple example of this in my VMD library doc. Needless to say the VC++ preprocessor has never been a standard C++ conforming preprocessor. What's worse is that Microsoft has never provided a tool which shows what the VC++ preprocessor is actually doing when it expands a macro, but of course if it ever had it would have clearly showed the ways in which it was not C++ standard compliant, therefore embarassing Microsoft.
The general problem you are encountering in the VC++ preprocessor is that it often re-scans macro expansion when it should not be doing so according to the preprocessor rules of standard C++. I give a simple example of this in my VMD library doc.
Needless to say the VC++ preprocessor has never been a standard C++ conforming preprocessor. What's worse is that Microsoft has never provided a tool which shows what the VC++ preprocessor is actually doing when it expands a macro, but of course if it ever had it would have clearly showed the ways in which it was not C++ standard compliant, therefore embarassing Microsoft. I'm not a boost preprocessor expert, but you should give a try to /E (or /P) cl command line arguments which (at least in VS2005 :-D ) shows the pre-processed output, maybe it can give you a hint on where
the trouble is Lorenzo
On 3/3/2016 8:49 AM, rleigh@codelibre.net wrote:
Hi folks,
I've been trying to get Boost.Preprocessor to run a nested for loop over two sequences to output nested switch blocks and case statements. This works fine with GCC and clang. Unfortunately it's broken with MSVC. If anyone had any thoughts on what I might need to tweak to enable the code to work with MSVC, I'd be very appreciative. Even if it's as nasty as a big ifdef with an alternative set of macros!
This is the test case:
-------- #include
#include <iostream> #define LASERTYPE_VALUES (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER)
enum LaserType { BOOST_PP_SEQ_ENUM(LASERTYPE_VALUES) };
#define PP_SEQ_FOR_EACH_R_ID() BOOST_PP_SEQ_FOR_EACH_R #define PP_DEFER(x) x BOOST_PP_EMPTY()
#define LT_NESTED(maR, maToplevelType, maNestedType) \ std::cout << "Test nested: first=" << LaserType(maToplevelType) << " second=" << LaserType(maNestedType) << " \n";
#define LT_TOPLEVEL(maR, maUnused, maType) \ std::cout << "Test toplevel: " << LaserType(maType) << " \n"; \ PP_DEFER(PP_SEQ_FOR_EACH_R_ID)()(maR, LT_NESTED, maType, LASERTYPE_VALUES);
int main() { BOOST_PP_EXPAND(BOOST_PP_SEQ_FOR_EACH(LT_TOPLEVEL, %%, LASERTYPE_VALUES)); } --------
You can simplify your efforts to avoid the BOOST_PP_SEQ_FOR_EACH/BOOST_PP_SEQ_FOR_EACH_R nested recursion problem by replacing: #define LT_TOPLEVEL(maR, maUnused, maType) \ std::cout << "Test toplevel: " << LaserType(maType) << " \n"; \ PP_DEFER(PP_SEQ_FOR_EACH_R_ID)()(maR, LT_NESTED, maType, LASERTYPE_VALUES); with: #define LT_TOPLEVEL(maR, maUnused, maType) \ std::cout << "Test toplevel: " << LaserType(maType) << " \n"; \ BOOST_PP_IDENTITY(BOOST_PP_SEQ_FOR_EACH_R)()(maR, LT_NESTED, maType, LASERTYPE_VALUES); and getting rid of the PP_SEQ_FOR_EACH_R_ID() and PP_DEFER(x) macros. This will still work with gcc/clang but still fails with VC++. As I mentioned in another message in this thread VC++ will often rescan after macro replacement when it should not be doing so according to the C++ standard, and that is almost certainly what it is doing here to defeat your efforts.
On MSVC, I get this:
cl /EHsc /I \path\to\boost-1_60 /Fe:test-pp.exe test-pp.cpp Microsoft (R) C/C++ Optimizing Compiler Version 18.00.40629 for x64 Copyright (C) Microsoft Corporation. All rights reserved.
test-pp.cpp test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_VARIADIC_ELEM_3' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_BOOL' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_BOOL_I' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_VARIADIC_ELEM_2' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_DEC' test-pp.cpp(22) : warning C4003: not enough actual parameters for macro 'BOOST_PP_DEC_I' test-pp.cpp(22) : error C2065: 'BOOST_PP_SEQ_FOR_EACH_M' : undeclared identifier test-pp.cpp(22) : error C2065: 'BOOST_PP_TUPLE_EAT_2' : undeclared identifier test-pp.cpp(22) : error C2065: 'LT_NESTED' : undeclared identifier test-pp.cpp(22) : error C2064: term does not evaluate to a function taking 1 arguments test-pp.cpp(22) : error C2146: syntax error : missing ';' before identifier 'BOOST_PP_IIF_BOOST_PP_BOOL_' test-pp.cpp(22) : error C3861: 'BOOST_PP_IIF_BOOST_PP_BOOL_': identifier not found test-pp.cpp(22) : error C2065: 'BOOST_PP_FOR_3' : undeclared identifier test-pp.cpp(22) : error C2065: 'BOOST_PP_TUPLE_EAT_4' : undeclared identifier test-pp.cpp(22) : error C2059: syntax error : ',' test-pp.cpp(22) : error C3861: 'BOOST_PP_EXPAND': identifier not found test-pp.cpp(22) : error C2065: 'BOOST_PP_FOR_4' : undeclared identifier test-pp.cpp(22) : error C2065: 'BOOST_PP_FOR_5' : undeclared identifier test-pp.cpp(22) : error C2065: 'BOOST_PP_FOR_6' : undeclared identifier test-pp.cpp(22) : error C2065: 'BOOST_PP_FOR_7' : undeclared identifier test-pp.cpp(22) : error C2065: 'BOOST_PP_FOR_8' : undeclared identifier test-pp.cpp(22) : error C2065: 'BOOST_PP_FOR_9' : undeclared identifier test-pp.cpp(22) : error C2065: 'BOOST_PP_FOR_10' : undeclared identifier
I've spent hours tweaking the testcase to try to make this work, but so far without success. It doesn't help that I don't fully understand what specifically is broken with the MSVC preprocessor, or how to work around whatever is behaving in a non-stanadard way.
participants (5)
-
Edward Diener
-
Lorenzo Trivelli
-
paul Fultz
-
rleigh@codelibre.net
-
Roger Leigh