Как справиться с этой ситуацией (необходимо зарегистрировать функции с переменными аргументами) - PullRequest
1 голос
/ 26 октября 2011

Я ищу предложение о том, как справиться с этой ситуацией, поскольку все, что я до сих пор думал, не работает.

Я работаю над RPG-игрой и в настоящее время разрабатываю графическую систему.Моя графическая система состоит из серии ScreenStack, которые расположены в определенном порядке и затем прорисованы.

ScreenStack - это просто набор связанных экранов, а также уникальный идентификатор и порядок прорисовки.

т.е.

class ScreenStack
{
//Constructors, getters/setters etc.
private:
    std::string StackName;
    int DrawPriority;
    int UID;

    bool Valid;
    bool DrawStack;
    bool UpdateStack;
    bool SendInputs;
    bool DeleteStack;
    std::vector<screen_ptr> OwnedScreens; //screen_ptr is a shared_ptr around a Screen object
};

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

У меня есть менеджер экрана, который отвечает за хранение различных функций для создания стеков экрана (т. е. функция создания стека битвы будет создавать экран для стороны игрока, вражеской стороны, атакиэкран анимации, фон и пользовательский интерфейс).Каждой из различных функций создания стека экрана необходим свой набор параметров для его создания.То, что я делаю сейчас, это вручную добавляю функции создания стека в менеджер экрана по мере необходимости.Например, прямо сейчас у диспетчера экрана есть функция для создания стека экрана заголовка, стека меню пуска, стека битвы, стека внешнего мира, стека тайлов и т. Д.

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

Сначала я попытался добавить unordered_map<std::string, StackCreationFunction> с функцией StackCreationFunction, имеющей typedef'd, поскольку

boost::function<ScreenStack (Engine& engine, ScreenManager& manager, const std::string screenName, const int StackID, const std::vector<std::string>& TryToCopyScreens, ...)> 

... было от cstdargs.Идея заключалась в том, что каждый ScreenStack будет добавлять свою собственную функцию StackCreation на эту карту.Однако это не работает, так как boost :: function недопустима с ...

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

Любые предложения / лучшее решение будет с благодарностью, и я могупредоставьте более подробную информацию, если вышеупомянутое не было достаточно ясно

Спасибо

Ответы [ 3 ]

2 голосов
/ 26 октября 2011

Каждой из различных функций создания стека экрана необходим свой набор параметров для ее создания.

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

Наиболее вероятное решение - повысить :: связать все аргументы вашей функции StackCreatorFunction, которые обычно входят в аргументы ..., и зарегистрировать эту связанную версию вашей функции на неупорядоченной карте, которая может быть освобождена от ....

1 голос
/ 26 октября 2011

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

0 голосов
/ 26 октября 2011

Я не уверен, отвечает ли это на ваш вопрос, но если ваша задача - вызывать различные функции с разными сигнатурами из кода, подобного интерпретатору, вы можете (по крайней мере в GNU / Linux) использовать LibFFI (библиотека для интерфейса с внешними функциями) для этого.

...