2016-03-02 2 views
0

Связано с моим вопросом Alternative to expanding templates in a switch statement пытается получить Boost.Preprocessor для выполнения вложенного взаимодействия по последовательности.Использование BOOST_PP_SEQ_FOREACH_R для рекурсивно обрабатывать перечисления

#include <boost/preprocessor.hpp> 
#include <iostream> 

#define LASERTYPE_VALUES (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER) 

enum LaserType 
{ 
    BOOST_PP_SEQ_ENUM(LASERTYPE_VALUES) 
}; 

#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";   \ 
    BOOST_PP_SEQ_FOR_EACH_R(maR, LT_NESTED, maType, LASERTYPE_VALUES); 

int main() { 
    BOOST_PP_SEQ_FOR_EACH(LT_TOPLEVEL, %%, LASERTYPE_VALUES); 
} 

Это приводит к этой ошибке:

test-pp.cpp: In function ‘int main()’: 
test-pp.cpp:15:32: error: ‘LT_NESTED’ was not declared in this scope 
    BOOST_PP_SEQ_FOR_EACH_R(maR, LT_NESTED, maType, LASERTYPE_VALUES); 
           ^
/usr/include/boost/preprocessor/seq/for_each.hpp:49:57: note: in expansion of macro ‘LT_TOPLEVEL’ 
# define BOOST_PP_SEQ_FOR_EACH_M_I(r, macro, data, seq) macro(r, data, BOOST_PP_SEQ_HEAD(seq)) 
                 ^
test-pp.cpp:4:39: error: ‘EXCIMER’ cannot be used as a function 
#define LASERTYPE_VALUES (EXCIMER)(GAS)(METALVAPOR)(SOLIDSTATE)(DYE)(SEMICONDUCTOR)(FREEELECTRON)(OTHER) 
            ^
test-pp.cpp:15:51: note: in expansion of macro ‘LASERTYPE_VALUES’ 
    BOOST_PP_SEQ_FOR_EACH_R(maR, LT_NESTED, maType, LASERTYPE_VALUES); 

Упорядочивание макросы не помогает. Здесь что-то принципиально неверно, и это, вероятно, тривиально, но я еще не понял, как это сделать и не видел приличных примеров. Если бы у кого-то были какие-то предложения, мне было бы очень интересно узнать, что я здесь делаю неправильно.

https://groups.google.com/forum/#!topic/boost-list/jhN4NE9VAtg указывает, что я могу столкнуться с проблемами реентерации. Похоже, я мог бы использовать BOOST_PP_FOR непосредственно для макроса верхнего уровня. Если бы у кого-нибудь был пример этого, это было бы действительно полезно.

ответ

0

Я нашел обходной путь в https://groups.google.com/forum/#!topic/boost-devel-archive/Tbcs4nn4sPE, который дает такое решение:

#include <boost/preprocessor.hpp> 
#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)); 
} 

Это немного эзотерическим, но компилирует и функции по мере необходимости.

+0

Я говорил слишком рано. Он отлично работает с GCC и clang, но не с MSVC. Я еще не нашел обходного пути для выполнения этой работы с VC++. –