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.