Использование препроцессора boost для преобразования кортежа в строку

Я новичок в использовании препроцессора boost. Я хочу использовать эту библиотеку для создания имени из кортежа, например, у меня есть такой кортеж (float, string, int, bool), и я хочу построить что-то вроде этого "Foo<float, string, int, bool>". Я думал, что это должно быть легко, используя BOOST_PP_STRINGIZE, BOOST_PP_CAT и BOOST_PP_REPEAT, но я, к сожалению, не смог найти способ сгенерировать нужную строку.

Пожалуйста, дайте мне предложение о создании этой строки. Foo — это имя класса, и кортеж генерируется автоматически во время предварительной обработки.


person motam    schedule 24.01.2016    source источник


Ответы (1)


Вы можете использовать BOOST_PP_TUPLE_ENUM для получения расширения элементов кортежа, разделенных запятыми. Затем вы можете использовать #__VA_ARGS__ для создания результирующего списка. Посмотрите вживую:

#define STRINGIZE_ALL_I(...) #__VA_ARGS__
#define STRINGIZE_ALL(...) STRINGIZE_ALL_I(__VA_ARGS__)

#define MAKE_STRING(tuple) STRINGIZE_ALL(Foo<BOOST_PP_TUPLE_ENUM(tuple)>)

// "Foo<float, string, int, bool>"
MAKE_STRING((float, string, int, bool))

STRINGIZE_ALL_I существует по той же причине, по которой у вас есть дополнительный слой в STRINGIZE и CONCAT — для оценки макросов перед строкой. В этом случае вы получите строку, содержащую BOOST_PP_TUPLE_ENUM((…)), если вы пренебрегли двумя слоями.

Обратите внимание, что STRINGIZE_ALL вызывается со списком аргументов Foo<float, string, int, bool>. Это четыре аргумента, а не один.


Если вариативные макросы недоступны (например, C++98), вы можете воспользоваться тем фактом, что компилятор "abc" "def" превратит в "abcdef". Посмотрите вживую:

#define STRINGIZE_ALL_MACRO(s, state, x) state "," BOOST_PP_STRINGIZE(x)

#define STRINGIZE_ALL(seq)      \
    BOOST_PP_SEQ_FOLD_LEFT(     \
        STRINGIZE_ALL_MACRO,    \
        BOOST_PP_STRINGIZE(BOOST_PP_SEQ_HEAD(seq)), \
        BOOST_PP_SEQ_TAIL(seq)  \
    )

#define MAKE_STRING(size, tuple) \
    STRINGIZE_ALL(               \
        BOOST_PP_TUPLE_TO_SEQ(   \
            size,                \
            (Foo<BOOST_PP_TUPLE_ENUM(size, tuple)>) \
        )                        \
    )

// "Foo<float" "," "string" "," "int" "," "bool>"
MAKE_STRING(4, (float, string, int, bool))

Для этой версии ваш автоматически сгенерированный кортеж также должен генерировать размер. Вполне возможно создать кортеж (size, (elems)), который можно использовать с этим макросом.

person chris    schedule 24.01.2016