Есть ли какой-либо шаблон, эквивалентный функции виртуального шаблона? - PullRequest
2 голосов
/ 25 мая 2020

Я работаю над инструментом мониторинга, и я сосредотачиваюсь на низких издержках времени выполнения и простом API. Для переключения включения / выключения с минимальными затратами времени выполнения я решил использовать шаблон состояния, а для упрощения использования я собирался использовать пакеты параметров шаблона.

И теперь я впервые m борется за границу, разделяющую время компиляции и время выполнения, и, конечно, не может заставить работать функцию виртуального шаблона.

Я ищу обходной путь или эквивалентное решение с учетом следующих ограничений:

  • Самая низкая стоимость времени выполнения в состоянии «отключено»
  • Гибкий API
  • Соответствие Pre C ++ 17

И если это невозможно, то тоже хорошо ...

Пример кода:

static struct /*Disabled*/ State
{
    template <typename... Args>
    /*virtual*/ void operator()(const char * category, Args&&... args) { /*noop*/ }
} 
disabled;

static struct Enabled : State
{
    template <typename... Args>
    /*virtual*/ void operator()(const char * category, Args&&... args) { /*processing category and args*/ }
} 
enabled;

struct Monitor
{
    static State* state;

    template <typename... Args>
    static void write(const char * category, Args&&... args)
    {
        state->operator()(category, std::forward<Args>(args)...);
    }
};

State* Monitor::state = &enabled;

int main()
{
    Monitor::write("BulletCount", 42);
    Monitor::write("Spell", "EnergyShield", true);
}

код выше компилируется, но я никогда не смогу достичь состояния Enabled без виртуального наследования. Удаление шаблона и множество перегрузок сделают это, но если этого можно будет избежать, это может стать довольно элегантным решением.

Ответы [ 2 ]

0 голосов
/ 25 мая 2020

Вам не нужно никакого «состояния», только логический флаг «включен».

struct Monitor
{
    static bool enabled;

    template <typename... Args>
    static void write(const char * category, Args&&... args)
    {
        if (enabled) {
            do_write(category, std::forward<Args>(args)...);
        }
    }

    template <typename... Args>
    static void do_write(const char * category, Args&&... args) { /*processing category and args*/ }

};

bool Monitor::enabled = true;

Это экономит уровень косвенности по сравнению с подходом виртуальных методов и работает быстрее, чем указатели на -загрузка решения из-за отправки stati c в сочетании с одной ветвью (на самом деле несколько ветвей ссылаются на одну и ту же переменную, хотя еще более удобны для конвейера, чем динамическая c отправка).

Время выполнения Стоимость отключенного состояния - это всего лишь одна незанятая ветвь (и вызов самого write, он слишком велик, чтобы быть встроенным). Но ветвь не может быть удалена, если вы хотите сохранить возможность переключения состояния во время выполнения.

0 голосов
/ 25 мая 2020

Вы можете попробовать другой подход (основанный на композиции вместо наследования), который поддерживает шаблон, например:

enum state_enum
{
    ENABLED_ST,
    DISABLE_ST
};

struct State
{
    state_enum myState;

    State(state_enum theState):myState(theState)
    {}

    template <typename... Args>
    /*virtual*/ void operator()(const char * category, Args&&... args) 
    { 
        if(myState == DISABLE_ST)
        {
         // noop    
        }
        else if(myState == ENABLED_ST)
        {

        }
    }

};

static State enabled = State(ENABLED_ST);
static State disabled = State(DISABLE_ST);

struct Monitor
{
    static State* state;

    template <typename... Args>
    static void write(const char * category, Args&&... args)
    {
        state->operator()(category, std::forward<Args>(args)...);
    }
};

State* Monitor::state = &enabled;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...