Как я могу получить более быструю скорость компиляции с помощью boost.parameter, подобного синтаксису?
В настоящее время я использую boost.parameter с некоторыми заводскими функциями, и время компиляции становится непомерно высоким.
в настоящее время у меня есть общая картина, как это:
auto thing = makeThing(property1 = foo::bar, "myThing"_thingName);
где makeThing
имеет около 30 параметров, большинство из которых со значениями по умолчанию. Я хотел бы сохранить синтаксис "именованный параметр как" и возможность сопоставления параметров по типу, а не по позиции.
Как улучшить скорость компиляции, не меняя синтаксис на сайте вызовов моей фабрики?
примечание: судя по разнице между скоростью boost.MPL и, скажем, разбойничьей скоростью, мне кажется, что во время компиляции должно быть, по крайней мере, улучшение на порядок, если современные методы метапрограммирования использовались в эквиваленте boost.parameter.
Обновление: вот сокращенный пример того, что именно я делаю: во встроенном контексте "голого металла" у меня есть различные периферийные устройства, абстрагированные как сложные шаблонные классы в соответствии с идиомой проектирования классов на основе политики. Каждый класс требует много информации о конфигурации во время компиляции и использует только необходимые функциональные возможности (нельзя полагаться на оптимизатор, который удаляет неиспользуемый материал, потому что все взаимодействия SFR наблюдаемы, поэтому изменчивы, поэтому это недопустимо).
Эти классы, основанные на политиках, очень уродливы для пользователя, и большинство встроенных пользователей убегают с криком, если они видят <в общедоступном интерфейсе, поэтому я использую boost.parameter для создания сексуальной фабрики, которой они могут передавать все свои закодированные желания типа (как в стиле хана), и я генерирую класс как локальную статическую, подключая его к требуемым ISR и передавая обратно дескриптор.
namespace usb
{
BOOST_PARAMETER_NAME(hw)
BOOST_PARAMETER_NAME(vid)
BOOST_PARAMETER_NAME(pid)
BOOST_PARAMETER_NAME(device_class)
BOOST_PARAMETER_NAME(max_packet_ep0)
BOOST_PARAMETER_NAME(max_packet)
BOOST_PARAMETER_NAME(packet_pool_size)
BOOST_PARAMETER_NAME(device_description)
BOOST_PARAMETER_NAME(device_calss_description)
BOOST_PARAMETER_NAME(can_power_down)
BOOST_PARAMETER_NAME(stall_supported)
BOOST_PARAMETER_NAME(setup_packet_timeout)
//...
BOOST_PARAMETER_FUNCTION(
(usb_handle),
make,
tag,
(required(hw, *))
(optional
(vid, *, 0x6001_ci)
(pid, *, 0x1234_ci)
(device_class, *, cdc_class{})
(max_packet_ep0, *, 8_ci)
(max_packet, *, 64_ci)
(packet_pool_size, *, 12_ci)
(device_description, *, "")
(device_calss_description, *, "")
(can_power_down, *, 0_ci)
(stall_supported, *, 0_ci)
(setup_packet_timeout, *, 100_ci)
)
)
{
// makes a local static policy based class taylored at compile time
// to support only the specified features
return{}; //returns a handle to the local static
}
}
Большинство заводов имеют 10-25 параметров, и время препроцессора кажется убийственным. Это занимает около 1-5 секунд на фабрику, независимо от того, действительно ли пользователь вызывает функцию или нет.
обновление 2: хорошо, щедрость закончилась, так что, похоже, решения нет. Если я найду время, я напишу замену boost.parameter и свяжу это здесь. Было бы также неплохо сделать так, чтобы возвращаемый тип именованной функции параметра зависел от типов ввода, чтобы приблизиться к семантике стиля boost.hana.
1 ответ
Вы можете реализовать статические объекты via global constexpr, например:
struct init_
{
my_class operator()(int i) {return i;}
my_class operator= (int i) {return i;}
};
consexpr static init_ init;
//make function
template<typename ...Args>
thingy make(Args&&...args);
auto x = make(init=42);
Возможно, вам придется добавить constexpr ctor в init_. Затем вы можете использовать boost.fusion или boost.hana, чтобы получить for_each для последовательности и инициализировать ваш тип.
struct thingy { int x;};
struct x_init
{
int init;
x_init (int i) : init(i) {};
void operator()(thingy & t)
{ t.x = init;}
};
struct x_
{
constexpr x_() {};
x_init operator()(int i) const {return i;}
x_init operator= (int i) const {return i;}
};
constexpr static x_ x;
template<typename ...Args>
thingy make(Args &&...)
{
thingy t;
auto vec = boost::fusion::make_vector(std::forward<Args>(args)...);
boost::fusion::for_each(vec, [t](auto & init){init(t);});
}
auto t = make(x=42);
Boost.Process фактически использует это, если вы загляните в мой репозиторий на github, вы найдете довольно сложную версию этого.