Подтвердить что ты не робот

Как ускорить скорость компиляции с помощью синтаксиса boost.parameter?

В настоящее время я использую boost.parameter с некоторыми функциями factory, а время компиляции становится непомерно высоким.

В настоящее время у меня есть общий шаблон, подобный этому:

auto thing = makeThing(property1 = foo::bar, "myThing"_thingName);

где makeThing имеет 30 параметров, большинство из которых имеют значения по умолчанию. Я хотел бы сохранить синтаксис "named parameter like" и возможность сопоставлять параметры по типу не по положению.

Как я могу получить лучшую скорость компиляции без изменения синтаксиса на сайте вызова моего factory?

Примечание: судя по разнице между скоростью boost.MPL и скоростью разгона бригады, мне кажется, что в момент компиляции должно быть по крайней мере на порядок, если современные методы мета-программирования использовались в эквиваленте boost.parameter.

update: - это сокращенный пример того, что именно я делаю: в оголенном металлическом встроенном контексте у меня разные периферийные устройства, абстрагированные как сложные шаблонные классы, следуя за идиомой дизайна на основе политики. Каждый класс получает много информации о конфигурации во время компиляции и использует только требуемую функциональность (не может полагаться на оптимизатора, чтобы вырезать неиспользуемые материалы, потому что все взаимодействия SFR наблюдаемы, поэтому они нестабильны, поэтому не допускаются).

Эти классы, основанные на политике, очень уродливы для пользователя для настройки, и большинство встроенных пользователей убегают от крика, если они видят < в публичном интерфейсе, поэтому я использую boost.parameter для создания сексуального factory, которому они могут передавать все свои закодированные пожелания (например, в стиле ханы), и я генерирую класс как локальный статический, подключая его к требуемым 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 секунд на factory независимо от того, действительно ли пользователь вызывает функцию или нет.

обновить 2:, а награда закончилась, поэтому похоже, что решения нет. Если я найду время, я напишу замену boost.parameter и свяжу его здесь. Было бы также полезно, чтобы возвращаемый тип именованной функции параметра зависел от типов ввода, чтобы приблизиться к семантике стиля boost.hana.

4b9b3361

Ответ 1

Вы можете реализовать сквозные глобальные объекты 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, вы найдете довольно сложную версию этого.