テンプレートを使ったゲーム開発

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
タンタル

テンプレートを使ったゲーム開発

#1

投稿記事 by タンタル » 4年前

お久しぶりです。今回もよろしくお願いいたします。
早速ですが、今回お聞きしたいことは、C/C++ゲーム開発におけるテンプレート(メタプログラミング)の活用方法です。

おかげさまで、クラスを用いたゲーム開発の理解はかなり深まったと思います。ポリモーフィズムやインターフェースなども、理解して使えるようになりました。
そこで次のステップとして、テンプレートについて理解を深めたいなと思っています。

ところがテンプレートに関する説明は、そのほとんどが
int add(int a, int b)とdouble add(double a, double b)の二つをオーバーロードするのって面倒でしょ?だったらふたつまとめて、templete<typename T> T add(T a, T b)にしよう!
みたいな記述が多く、それだけ?となってしまって、正直そこまでメリットを感じないですし、それでこれをどう使えと...となっております。

しかし、実際STLコンテナなどでテンプレートが使われてます。
テンプレートを使用することにメリットが多いから、目にする機会が多いのだと思います。
ですが、実際にゲーム開発でどのように利用されてるのか、そういった記述を見つけることができませんでした。

そこで、皆さんにお聞きしたいのは、実際にゲームプログラミングをしている中で、どのようにテンプレートを使用していますか?ということです。
STLコンテナで使ってるじゃないか、という話ではなく、自分でtempleteという単語を入力する機会についての話です。


ゲームには、プレイヤークラスや敵クラス、アイテムクラスなどがあるとして、すべてのクラスはupdate()関数を持っているとすると、
テンプレートでT t; t->update();みたいなことができて、一括してアップデートできるようになるのかな?などと思ったのですが、
別にそんなことするまでもなく、ポリモーフィズムで十分じゃないか?という結論になりました。

まったく活用方法のイメージがわきません。皆さんはどのようにテンプレートを使っていますか?
抽象的なしょうもない質問と思われるかもしれませんが、よろしくお願いします。

Rittai_3D
記事: 525
登録日時: 7年前

Re: テンプレートを使ったゲーム開発

#2

投稿記事 by Rittai_3D » 4年前

趣味でゲームプログラミングをしていますが、あまりテンプレートを使う機会はないですね(あくまで個人の感想)。
ときどき、

コード:

template< class T, std::size_t N >
constexpr auto get_array_num( T (&)[ N ] )
{
    return N;
}
というような関数は使いますけど・・・。

実際に書くとしたら

コード:

template< class T >
struct Rect_t
{
    T top, bottom;
    T left, right;

    // その他のコンストラクタ・オペレータのオーバーロード等を実装する
};

// こうやって使う
void test()
{
    auto rect_int = Rect_t< int > {}; // 座標が int 型のRect_t
    auto rect_float = Rect_t< float > {}; // 座標が float 型のRect_t
    auto rect_double = Rect_t< double > {}; // 座標が double 型のRect_t
}
こういう感じですかね・・・。
初心者です

タンタル

Re: テンプレートを使ったゲーム開発

#3

投稿記事 by タンタル » 4年前

Rittai_3Dさん、返信ありがとうございます。

そうですか...テンプレートはあまり使用されないのですね。
ゲームプログラミングにおいて使う機会がなのであれば、無理にテンプレートを使う必要はないので、それならこのままゲーム開発を続けていこうと思います。

ソースコードを提示していただき、ありがとうございます。
せっかく作っていただいたにもかかわらず、このようなことを言うのは大変申し訳ないのですが、
やはりそのようにテンプレートを使うことに、いまいちメリットを感じることができませんでした...
最悪全部キャスト変換できるんだから、doubleで宣言しておけばいいのでは?と思いました。

僕の経験や知識が不足しているために、理解しきれていないところがあると思いますので、
(実際、constexprもautoもいまいちわかっておりませんでした...)
もう少し、いろいろと自分で調べて勉強してみようと思います。

Rittai_3Dさん、本当にありがとうございました。

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: テンプレートを使ったゲーム開発

#4

投稿記事 by ISLe » 4年前

#もう解決になってた。

メタな使い方だと容量とかコンパイル時間とか予想外の状況になったりするので多用はしないですね。
スケジュール大事。

インターフェースの継承だとトップダウンオンリーですが
テンプレートを使うとトップダウンとボトムアップを組み合わせる自由度が上がります。

コード:

#include <iostream>
#include <algorithm>
using namespace std;
struct Base
{
    virtual void Update() = 0;
};
struct ClassA : public Base
{
    int index;
    ClassA(int i) : index(i) {};
    void Update() override
    {
        cout << "ClassA::Update(" << index << ")" << endl;
    }
    void UpdateA()
    {
        cout << "ClassA::UpdateA(" << index << ")" << endl;
    }
};
void AdaptA(ClassA &t) {
    t.UpdateA();
}
struct AdaptorA {
    void operator()(ClassA &t) {
        t.UpdateA();
    }
};
int main()
{
    Base *a1[] = { new ClassA(1), new ClassA(2), new ClassA(3) };
    ClassA a2[] = { 4, 5, 6 };

    // 継承ではインターフェースとして定義されたメンバ関数しか呼び出せない
    for (Base *b : a1) b->Update();

    // テンプレートを使うと(間接的だが)任意のメンバ関数を随時呼び出せる
    for_each(begin(a2), end(a2), AdaptA); // 関数
    for_each(begin(a2), end(a2), AdaptorA()); // 関数オブジェクト
    for_each(begin(a2), end(a2), [](ClassA &o) { o.UpdateA(); }); // ラムダ式
}
こんな具合にstd::for_eachを使うと任意のメンバ関数を呼び出せるわけですが
同様の仕組みで、更新関数や描画関数として任意のメンバ関数を呼び出せるマネージャクラスなんてのも作れます。
そんなとき自分でtempleteという単語を入力します。

任意のメンバ関数を更新関数や描画関数にできれば継承が要らなくなって
継承を別の用途(ガベージコレクタ的なこととか)に使うことができるようになります。

組み合わせの自由度が高いと、複雑なものも分解しやすく単純化しやすいです。
コードが読みやすくなるし、モジュール化も進みます。

閉鎖

“C言語何でも質問掲示板” へ戻る