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.