3

Необходимо создать макрос для создания набора перегрузок структуры, специализированной по тегу и индексу. Я попытался следующие:Создайте набор тегов и индексированных специализаций шаблона класса с использованием Boost.Preprocessor

#include <boost/preprocessor/seq/for_each_i.hpp> 

template< typename /*tag*/, int /*index*/ > 
struct S; 

#define GEN(ignored, tilda, index, type_name) \ 
    template<> struct S< struct BOOST_PP_SEQ_TAIL(type_name), index > \ 
    { BOOST_PP_SEQ_HEAD(type_name) BOOST_PP_SEQ_TAIL(type_name); }; 

#if 1 
BOOST_PP_SEQ_FOR_EACH_I(GEN, ~, ((int)(i))) 
#else 
// above should be equiv to: 
template<> struct S< struct i, 0 > { int i; }; 
#endif 

int main() 
{ 
    S< i, 0 >{}.i; // check if accessible 
} 

Но получить ошибку:

prog.cc:8:111: error: wrong number of template arguments (1, should be 2) 
#define GEN(ignored, tilda, index, type_name) template<> struct S< struct BOOST_PP_SEQ_TAIL(type_name), index > { BOOST_PP_SEQ_HEAD(type_name) BOOST_PP_SEQ_TAIL(type_name); }; 
                              ^
/usr/local/boost-1.62.0/include/boost/preprocessor/seq/for_each_i.hpp:85:66: note: in expansion of macro 'GEN' 
# define BOOST_PP_SEQ_FOR_EACH_I_M_I(r, macro, data, seq, i, sz) macro(r, data, i, BOOST_PP_SEQ_HEAD(seq)) 
                    ^~~~~ 
/usr/local/boost-1.62.0/include/boost/preprocessor/seq/for_each_i.hpp:80:49: note: in expansion of macro 'BOOST_PP_SEQ_FOR_EACH_I_M_I' 
# define BOOST_PP_SEQ_FOR_EACH_I_M_IM(r, im) BOOST_PP_SEQ_FOR_EACH_I_M_I(r, im) 
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/local/boost-1.62.0/include/boost/preprocessor/seq/for_each_i.hpp:79:45: note: in expansion of macro 'BOOST_PP_SEQ_FOR_EACH_I_M_IM' 
# define BOOST_PP_SEQ_FOR_EACH_I_M(r, x) BOOST_PP_SEQ_FOR_EACH_I_M_IM(r, BOOST_PP_TUPLE_REM_5 x) 
              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/local/boost-1.62.0/include/boost/preprocessor/seq/for_each_i.hpp:79:77: note: in expansion of macro 'BOOST_PP_TUPLE_REM_5' 
# define BOOST_PP_SEQ_FOR_EACH_I_M(r, x) BOOST_PP_SEQ_FOR_EACH_I_M_IM(r, BOOST_PP_TUPLE_REM_5 x) 
                      ^~~~~~~~~~~~~~~~~~~~ 
/usr/local/boost-1.62.0/include/boost/preprocessor/control/iif.hpp:32:31: note: in expansion of macro 'BOOST_PP_SEQ_FOR_EACH_I_M' 
# define BOOST_PP_IIF_1(t, f) t 
          ^
/usr/local/boost-1.62.0/include/boost/preprocessor/repetition/detail/for.hpp:22:37: note: in expansion of macro 'BOOST_PP_FOR_1_C' 
# define BOOST_PP_FOR_1(s, p, o, m) BOOST_PP_FOR_1_C(BOOST_PP_BOOL(p(2, s)), s, p, o, m) 
            ^~~~~~~~~~~~~~~~ 
/usr/local/boost-1.62.0/include/boost/preprocessor/cat.hpp:29:34: note: in expansion of macro 'BOOST_PP_FOR_1' 
# define BOOST_PP_CAT_I(a, b) a ## b 
           ^
/usr/local/boost-1.62.0/include/boost/preprocessor/control/iif.hpp:32:31: note: in expansion of macro 'BOOST_PP_SEQ_FOR_EACH_I_DETAIL_CHECK_EXEC' 
# define BOOST_PP_IIF_1(t, f) t 
          ^
/usr/local/boost-1.62.0/include/boost/preprocessor/seq/for_each_i.hpp:30:55: note: in expansion of macro 'BOOST_PP_SEQ_FOR_EACH_I_DETAIL_CHECK' 
# define BOOST_PP_SEQ_FOR_EACH_I(macro, data, seq) BOOST_PP_SEQ_FOR_EACH_I_DETAIL_CHECK(macro, data, seq) 
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
prog.cc:10:1: note: in expansion of macro 'BOOST_PP_SEQ_FOR_EACH_I' 
BOOST_PP_SEQ_FOR_EACH_I(GEN, ~, ((int)(i))) 
^~~~~~~~~~~~~~~~~~~~~~~ 
prog.cc:6:8: note: provided for 'template<class, long unsigned int <anonymous> > struct S' 
struct S; 
     ^
prog.cc: In function 'int main()': 
prog.cc:16:8: error: 'i' was not declared in this scope 
    S< i, 0 >{}.i; // check if accessible 
     ^
prog.cc:16:13: error: template argument 1 is invalid 
    S< i, 0 >{}.i; // check if accessible 
      ^

Кажется, что struct BOOST_PP_SEQ_TAIL(type_name) часть макроса не может быть обработан правильно, но почему? Если я заменил первое вхождение BOOST_PP_SEQ_TAIL(type_name) на i, тогда код компилируется штрафом.

Что является источником ошибки?

+0

Ммм, я не уверен, что вы имеете в виду ... Разве я что-нибудь сломать? – Quentin

+0

О! Это форматирование блока кода, с подсказкой '' для удаления цветов :) – Quentin

+0

@Quentin Мне интересно, как восстановить оригинальные таблицы в цитатах (которые начинаются с '>' mark). – Orient

ответ

2

Для краткости я удалил #include <cstdint>, но попробуйте выполнить компиляцию с -P -E, который выведет только результат выполнения препроцессора, что весьма полезно при отладке программ Boost.PP.

Выход что:

template< typename , int > 
struct S; 
template<> struct S< struct (i), 0 > { int (i); }; 
int main() 
{ 
    S< i, 0 >{}.i; 
} 

, из которого ошибка сразу видно: struct (i) и int (i) являются недействительными синтаксис.

This answer может помочь вам в этом, что с этим делать.

Вот мое решение этой проблемы, которая заключается в создании своих собственных маленьких кортежей-доступа макросы:

#include <boost/preprocessor/seq/for_each_i.hpp> 

template< typename /*tag*/, int /*index*/ > 
struct S; 

#define FIRST(a, b) a 
#define SECOND(a, b) b 

#define GEN(ignored, tilda, index, type_name)       \ 
    template<> struct S< struct SECOND type_name, index > \ 
    { FIRST type_name SECOND type_name; }; 

#if 1 
BOOST_PP_SEQ_FOR_EACH_I(GEN, ~, ((int, i))) 
#else 
// above should be equiv to: 
template<> struct S< struct i, 0 > { int i; }; 
#endif 

int main() 
{ 
    S< i, 0 >{}.i; // check if accessible 
} 
+0

'int (i);' хороший синтаксис даже в списке параметров функции. Но, похоже, вы находите источник ошибок. – Orient

+0

Отличное решение! – Orient

+0

Странно, потому что документация по boost PP говорила, что 'BOOST_PP_SEQ_TAIL' может вернуть unparenthesed элемент кортежа. – Orient

Смежные вопросы