C ++ Как привязать аргументы к функциям с одинаковым типом возврата и сохранить их все в одном контейнере - PullRequest
0 голосов
/ 21 мая 2018

Намерение и контекст

У меня есть класс с именем Component.Это выглядит примерно так (PSEUDO CODE):

template <class t>
class Component{
private:
    map<Entity, List<t>> attachedEntities;
public:
//Some other stuff like constructors, setters and getters etc.
     template<typename... Args>
     void addTo(const Entity &en, Args...args)
    {
        this->addTo(en,std::make_shared<t>(std::forward<Args>(args)...));
    }

    template < typename U, typename std::enable_if< std::is_base_of<t, U>::value, U>::type* = nullptr >
    void addTo( const Entity &en,U* ptr)
    {
        this->addTo(en,shared_ptr<t>(ptr));
    }
    void addTo(const Entity &en,const std::shared_ptr<t> ptr)
    {
        /*
            Does the actual adding to the map
        */
    }
}

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

В образовательных целях я не хочу писать оболочки для переданных переменных.

Как видите, класс Component имеет 3 функции addTo.В настоящее время моя система представляет собой простую систему компонентов, в которой объект представляет собой UUID, который используется в качестве ключа в картах.Эти карты, когда приводятся в контекст с одним UUID, могут затем «сформировать» полный объект.

Например, у объекта может быть запись в

  • StringComponent
  • TextureComponent
  • ModelComponent

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

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

Пуля может иметь:

  • Модель, представляющую, как она выглядит
  • CollissionBox для обнаружения, когда с ним сталкивается материал
  • Звук, который воспроизводится при воздействии
  • Какой-то тег (StringComponent), чтобы убедиться, что функция обновления обновляет его должным образом (так чтобудет иметь тег «Bullet_big»)

Опять же, это работает, однако прямо сейчас, только делая Enitity невосприимчивой к удалению и просто имея другие пули в качестве Копий этой сущности.Это плохо по следующим причинам:

  • Это добавляет в игру что-то, с чем можно взаимодействовать, но нельзя удалить.Если бы я сделал это так, что он был бы недоступен для всех, кроме удалений, это все равно добавило бы накладные расходы, потому что некоторая замена сортировки должна быть дана, когда get или set вызывается
  • Это непригодный для использования элемент на каждой карте,Это может стать проблемой с более крупными программами, где потенциально существуют сотни таких «шаблонов», плавающих вокруг
  • . Если шаблон удаляется, либо из-за недосмотра разработчика, либо из-за ошибки, копии, скорее всего, вызовутпотерпеть крах или начать действовать странно.

С чем я на самом деле борюсь

Сейчас я хочу написать Blueprint класс

Этот класс должен быть просто:

  • Контейнер, который можно использовать для создания новых сущностей, имеющих все одинаковые компоненты.
  • Без фактического зачисления в какие-либо карты.
  • А-а-а, без необходимости вручную проверять каждое имя компонента, чтобы определить, какой из них добавить (это было бы глупо).

Вот то, о чем я думал:

class Blueprint{
private:
    vector<function<???>> frozenAddFunctions; //Some way of storing all the functions with the init paramters but WITHOUT the entity specified;
public:
    template<t,typename... Args>
    void addTo(Component<t>, Args...args){
    //Somehow binding the approperate addTo overload to the arguments
    }
    void applyOnto(Entity &en){
        for(function f:this->frozenAddFunctions){
            f(en); //somehow invoke the addTo functions onto the Entity.
        }
    }

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

Заранее спасибо.

Надеюсь, это исполнение былолучше.

1 Ответ

0 голосов
/ 21 мая 2018

Кажется, вы хотите:

class Blueprint
{
private:
    std::vector<std::function<void(Entity &)>> functions;
public:
    template<typename T, typename... Args>
    void addTo(Component<T>& component, Args...args)
    {
        functions.emplace_back([=, &component](Entity& ent)
        {
            component.AddTo(ent, args...);
        });
    }

    void applyOnto(Entity &en)
    {
        for(const auto& f : functions){
            f(en);
        }
    }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...