MrNexeon
@MrNexeon

Использование вариативного шаблона функции без аргументов?

У меня есть объект класса Entity, который содержит список компонентов std::list<Component*> m_components

Сами компоненты представляют из себя классы, наследуемые от базового класса Component

С помощью функции bool HasComponent<T> я могу проверить наличие определенного компонента:

template<typename T> bool HasComponent<T> {
 T instance; //создаю экземпляр компонента

 for (auto component : m_components)  //for each 
 if (component->GetType() == instance.GetType()) { //если типы компонентов совпадают
 return true; //возвращаем true
}

//...

Entity mario;
if (mario.HasComponent<Velocity>) print("Mario can move!"); //пример использования

Но как мне одной функцией проверить наличие сразу нескольких компонентов?

bool HasComponents<Health, Velocity, Sprite>();

Я знаю что это можно реализовать с помощью вариативных шаблонов, но нахожу их применение лишь с аргументами, вроде этого: void foo(Args... args).

Вопрос: Как реализовать алгоритм для моего случая?
  • Вопрос задан
  • 461 просмотр
Решения вопроса 1
@MarkusD Куратор тега C++
все время мелю чепуху :)
Смотри... Т.к. в предложенном коде я уже вижу немного бардака, то и вариант предлагаю слегка бардачный. :)
Эту задачу можно решить сразу несколькими способами метапрограммирования. Предложенное решение - одно из них.
template< typename TComponentType >
bool HasComponent()
{
	return ...;
};

template< typename... TComponentTypes >
bool HasComponents()
{
	// Это тип предиката для проверки наличия одного компонента.
	using CheckingPred	= bool (*)();
	
	// Это тип листа проверки.
	using PredList		= std::array<CheckingPred, sizeof...( TComponentTypes )>;
	
	// Определяем лист проверки, следи за руками... :-)
	PredList predicates{{ HasComponent<TComponentTypes>... }};
	
	// Проверяем!
	return std::all_of( predicates.begin(), predicates.end(), []( CheckingPred stored_pred ) -> bool { return stored_pred(); } );
};


Сразу заостряю внимание на форматировании и стиле. Так сказать, что понятнее и удобнее читается? :)

UPD:
Еще предлагаю полистать библиотеку одного интересного товарища: https://github.com/alecthomas/entityx
Как я понимаю, тебе хочется попробовать реализовать ECS. EntityX - одна из самых прямых ECS библиотек на плюсах, если не сказать - самая прямая.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
@MiiNiPaa
К примеру на С++17:

1) Переименовываете ваш текущий HasComponent в HasComponent_impl и делаете его приватным.

2) Создаёте новый HasComponent:
template<typename... Ts> bool HasComponent()
{
    return (HasComponent_impl<Ts>() && ...);
}
Пример.

Квадратичная сложность, конечно. Можно сделать лучше, но нужно ли?
Ответ написан
Adamos
@Adamos
Я бы в вашем случае погасил лампадку перед портретом Александреску и перестал насиловать компилятор.
Добиваясь поставленной цели, вы запутываете код - и при этом решительно ни в чем не выигрываете.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы