@toster_bodnar

Variadic template, как перебрать в шаблоне все типы по очереди?

Есть код:

...

template<typename T>
T get(T value)
{
   return static_cast<T>(this->vec.find(value));
}

...

template<typename ... T>
void some_func(typename identity<std::function<void(T ...)>>::type func)
{
   auto value1 = get< ? >( 1 ); // для Т1
   auto value2 = get< ? >( 2 ); // для Т2
   ...
   auto valueN = get< ? >( N ); // для ТN
   func(value1, value2, ... valueN);
}


Как можно по очереди сделать в функции some_func вызов get для каждого из типов Т ? Что бы потом передать их в func

что бы можно было вызвать это так:

some_func<int, int, int>([](int a, int b, int c){
     std::cout << a << b << c << std::endl;
    })
  • Вопрос задан
  • 77 просмотров
Решения вопроса 1
@MarkusD Куратор тега C++
все время мелю чепуху :)
Пусть у нас есть некий аксессор:
template< typename TComponent >
TComponent* const QueryComponent();


Пусть у нас есть, для простоты, некоторый обработчик:
void PerformWorkflow( A*, B*, C* );
Тут A, B и C - это типы компонентов.

Чтобы подружить обработчик с аксессором необходимых ему компонентов, понадобится самый простой Parameter pack expansion.
template< typename... TComponents >
void ApplyComponents( void (*workflow)( TComponents*... ) )
{
	workflow( QueryComponent<TComponents>()... );
}

Здесь можно посмотреть как работает пример этого кода.

В комментарии я вижу несоответствие типа параметра функции для each и типа результата get. Стоит напомнить что разыменование nullptr, который может вернуть get, приводит к неопределенному поведению [?].
Поэтому, если распаковку переписать на *QueryComponent<TComponents>()..., т.е. на лету разыменовывать полученные указатели, то перед запуском функции для твоей entity следует убедиться что у нее есть все необходимые компоненты. Такая проверка является необходимой для запуска систем в ECS, т.к. система должна обрабатывать только удовлетворяющие своим фильтрам сущности.

Для этого уже потребуется использовать Fold expression из C++17.
template <typename... T>
void each(typename identity<std::function<void(T& ...)>>::type func)
{
	for(auto &entity: m_entities)
	{
		if( !( (entity.HasComponent<T>() && ...) ) )
		{
			continue;
		}
		
		func( *entity.get<T>()... );
	}
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

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