C++ Variadic Macros в Boost.Fusion?
-
15-11-2019 - |
Вопрос
Итак, согласно этому отвечать, C++ не поддерживает вариативные макросы, а стандарт C++ нигде не упоминает вариативные макросы.Я знаю, что в C99 появились вариативные макросы с __VA_ARGS__
, а некоторые компиляторы C++ (например, GCC) даже предоставляют расширения, позволяющие это сделать в C++, но факт остается фактом: макросы с переменным числом вариантов просто не являются частью стандартного C++.
Теперь в Boost.Fusion есть функция, с помощью которой вы можете привязать последовательность Fusion к произвольному классу или структуре, используя BOOST_FUSION_ADAPT_STRUCT
макрос.Это позволяет вам использовать ваш класс или структуру, как если бы это была последовательность Fusion.
Вот пример того, как это используется (взято из документации Boost):
namespace demo
{
struct employee
{
std::string name;
int age;
};
}
// demo::employee is now a Fusion sequence
BOOST_FUSION_ADAPT_STRUCT(
demo::employee,
(std::string, name)
(int, age))
Теперь, как этот код возможен без вариативных макросов?А BOOST_FUSION_ADAPT_STRUCT
Кажется, что макрос принимает произвольное количество аргументов, поскольку предположительно он может работать с любым произвольным пользовательским классом или структурой.
Я знаю, что Boost славится интересными изменениями в C++, но это кажется совершенно невозможным без поддержки компилятора.Так какое же волшебство делает Boost.Fusion, чтобы осуществить это?
ПС:Да, я знаю, что Boost имеет открытый исходный код.Первое, что я сделал, это посмотрел исходный код.Кажется, он использует библиотеку препроцессора Boost для какого-то объединения макросов.Но я не понимаю, как это может работать с любым произвольным количеством аргументов, а исходный код представляет собой очень плотную коллекцию кода препроцессора, которую очень сложно понять.
Решение
BOOST_FUSION_ADAPT_STRUCT(
demo::employee,
(std::string, name)
(int, age))
Это один макрос, который принимает два аргумента:Аргумент 1:Демо :: Аргумент сотрудника 2:(std::string, name)(int, age)
Аргумент 2 объединяется со строкой для формирования другого вызова макроса, который также принимает 2 параметра:
BOOST_FUSION_SOME_INTERNAL_MACRO(std::string, name)
BOOST_FUSION_SOME_INTERNAL_MACRO(int, age)