4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【C++】クラステンプレートでパラメータパックを複数もらう

Posted at

#こんな状況に出くわした
複雑なテンプレートを書いているとこんな状況に出くわす

// 2つ以上のパラメータパックが欲しい!
template<typename... Components, typename... Events>
class ComponentManager
{
	// ・・・
};

でもこれは当然コンパイルエラーになる
なぜならパラメータパックは最後の引数にしか使えないからだ

// できたとしても区切りがつかなくなる
ComponentManager<Component1, Component2, Event1, Event2> comp;

そこでタプル**std::tuple**さんに活躍してもらうことにしましょう。1

#std::tupleを使ってパラメータパックをまとめる

std::tupleを使うとこのようにまとめることができます。

// templateの中にタプル
using Components = ComponentManager<
	std::tuple<
		Component1,
		Component2
	>,
	std::tuple<
		Event1,
		Event2
	>
>;

それでは実装してみましょう。

少し不思議な書き方ですがとてもシンプルです。

template<typename Components, typename Events>
class ComponentManager;

template<typename... Components, typename... Events>
class ComponentManager<std::tuple<Components...>, std::tuple<Events...>>
{
	// ・・・
}

ぜひ、試してみてください。

#応用

これを応用すればパラメータパックの2重ループが作れます

// 出力
template<typename Event, typename Component>
void PrintEventComponent()
{
	std::cout << "Event:" << typeid(Event).name() << ", "
		<< "Component: " << typeid(Component).name() << std::endl;
}

template<typename Components, typename Events>
class ComponentManager;

template<typename... Components, typename... Events>
class ComponentManager<std::tuple<Components...>, std::tuple<Events...>>
{
private:
	// 内側のループ (Components)
	template<typename Event>
	static void InitializeEvent()
	{
		using accumulator_type = int[];
		accumulator_type accumulator = { 0, (PrintEventComponent<Event, Components>(), 0)... };
		(void)accumulator;
	}

public:
	// 外側のループ (Events)
	static void InitializeEvents()
	{
		using accumulator_type = int[];
		accumulator_type accumulator = { 0, (InitializeEvent<Events>(), 0)... };
		(void)accumulator;
	}
};
struct Component1 {};
struct Component2 {};
struct Event1 {};
struct Event2 {};

int main()
{
	// usingを使えば何度も使うことができる
	using Components = ComponentManager<std::tuple<Component1, Component2>, std::tuple<Event1, Event2>>;
	Components::InitializeEvents();

	return 0;
}
Event: struct Event1, Component: struct Component1
Event: struct Event1, Component: struct Component2
Event: struct Event2, Component: struct Component1
Event: struct Event2, Component: struct Component2
  1. パラメータパックがまとめられるクラスなら何でもいいです。

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?