Шаблон команды без виртуальных функций (C ++) - PullRequest
4 голосов
/ 11 июня 2009

Из соображений производительности я использую шаблон шаблона Curiious Reoccuring , чтобы избежать виртуальных функций. У меня много маленьких команд, которые выполняются миллионы раз. Я пытаюсь вписать это в шаблон командования. Я хочу добавить тонны команд в очередь, а затем перебирать их, выполняя каждую по одной. Каждая команда использует CRTP, чтобы избежать виртуальных функций. Проблема, с которой я сталкиваюсь, состоит в том, что шаблон Command обычно реализуется с использованием вектора указателей. Но когда класс Command является шаблонным, становится трудно обойти общие указатели команд. Я не эксперт по C ++, так что, возможно, есть очевидный способ сохранить вектор шаблонных объектов команд? Я пытался использовать что-то вроде:

boost:ptr_vector commands;
AddCommand(Command* command) {
  commands.push_back(command);
}

Проблема Command не в типе, поэтому Command* command выдает ошибку компиляции. Мне нужно использовать Command<CommandType>, но это не сработает, потому что мне нужна очередь для хранения различных типов команд.

Есть идеи для решения? Или виртуальные функции - единственный вариант?

ДОБАВЛЕНО: Командные объекты являются частью алгоритма моделирования Монте-Карло. Таким образом, вы можете иметь, что Command - это случайное число из нормального распределения, где параметры нормального распределения являются частью класса. Таким образом, шаблон команды подходит очень хорошо. У меня есть много вызовов, в определенном порядке, к функциям, которые должны поддерживать состояние.

Ответы [ 3 ]

11 голосов
/ 11 июня 2009

CRTP делает свое дело, разрешая тип времени выполнения объекта во время компиляции, чтобы компилятор мог встроить вызовы функции. Если у вас есть вектор указателей на универсальный тип, компилятор не сможет определить конкретный конкретный тип и не сможет выполнить его разрешение во время компиляции.

Исходя из информации, которую вы имеете в своем вопросе, я думаю, что виртуальные функции - ваш лучший вариант. Однако виртуальные функции не такие медленные. Конечно, они медленнее встроенной функции, но во многих случаях они достаточно быстрые! Особенно, если ваш процесс ограничен временем ввода-вывода, а не временем обработки.

Один из ответов на на этот вопрос содержит более подробное обсуждение этого вопроса. Подводя итог, можно сказать, что издержки на вызов виртуальной функции будут измеряться в наносекундах. Это сложнее, чем это, но дело в том, что вам не следует бояться виртуальных функций, если ваша функция не выполняет действительно тривиальные задачи, например, одно назначение. Вы сказали, что ваши команды были маленькими, так что, возможно, это так. Я бы попробовал сделать быстрый прототип с виртуальными функциями и посмотреть, дает ли это приемлемую производительность.

1 голос
/ 12 июня 2009

Я не могу сказать, часто или редко меняется ваша очередь команд.

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

Просто распечатайте программу, чтобы выполнить необходимые действия, скомпилируйте и свяжите dll на лету и загрузите ее. Это должно занять около секунды. Нет классов, объектов или диспетчеризации. И если вы сделаете один шаг, вы почти не увидите циклов, которые не вносят существенный вклад в ваш ответ.

1 голос
/ 11 июня 2009

Если вы не строите свою очередь команд во время компиляции, то, что вы хотите, невозможно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...