2

タイトルに申し訳ありませんが、より適切な名前が見つかりませんでした。誰かがより良いものを持っていれば、私は喜んでそれを変更します.

ソリッド ジオメトリ オブジェクトのセットがあるとします。

struct ray { ... };
struct plane { ... };
struct box { .... };
struct sphere { .... };

現在、交差アルゴリズム用のテンプレート化された関数を考えています。これにより、実行時にチェックする型に応じて関数の特殊なバージョンを作成できます。

template <typename operand_type1, 
          typename operand_type2> 
          RET_DATA check_intersection(operand_type1 operand1, operand_type2 operand2){ ... };

ray/shphere 交差の場合、次の実装を提供します。

template<> RET_DATA check_intersection<ray, sphere>(ray operand1, sphere operand2){ ... };

RET_DATA は意図的に未定義のままにしました。これは、それぞれの専門分野に応じて、異なる情報を返す必要がある場合があるためです。たとえば、この場合、交差点の数 (存在する場合) と関連するポイントを返すことができます。球-球の場合、交差のボリュームを返すことができます。問題は、このテンプレートのユーザーが知る必要がある新しい (戻り値の) 型も作成する必要があることです。

私の現在の最良の候補のアイデアは、ファンクターを作成し、各タイプに特化することです。ファンクター内で、それぞれの特殊化に共通の名前を持つ return 構造体を定義します (すなわち、result ):

/** templated functor */
template<typename T1, typename T2> struct check_intersect {
    typedef intersection_data<T1, T2> result;

    check_intersect(T1 operand1, T2 operand2) : operand1(operand1), operand2(operand2) {}

    result operator()(T1 operand1, T2 operand2){ ... }  
};

/** tempalted auxiliar return data type */
template<typename T1, typename T2> struct intersection_data { ... }

次に、データ型に応じて両方に特殊化を提供します。これは多かれ少なかれ、次の使用パターンで終わります。

 check_intersect<ray, sphere>::result ret = check_intersect<ray, sphere>(my_ray, my_sphere);

最新の IDE を使用すると、問題はある程度軽減されますが、ユーザーは依然として結果を得るためにインターフェイスを推測する必要があります。これは私がそれについて好きではないことです。

このアプローチは欠陥がありますか? 今後のソリッドジオメトリタイプの拡張性を解決するためのより良い設計アイデアはありますか? これは最もエレガントなアプローチですか?

テンプレートはこれに適したツールではないかもしれません。ケースごとに異なる機能を提供することができます....

ありがとうございました。

4

1 に答える 1

2
  1. 一般的な実装がない限り、テンプレートを使用しないでください。実際に の関数本体がない限りtemplate< typename x, typename y > check_intersection( x, y )、宣言しないでください。

  2. テンプレートの特殊化の代わりにオーバーロードを使用します。オーバーロードは、この種の問題を解決するために設計されたツールです。専門が違います。一般的なテンプレートと一緒に特定のオーバーロードを使用しても問題ありません。

  3. 異なる RET_DATA タイプの基本クラスを使用します。virtual定数参照にバインドする場合、これにはデストラクタは必要ありません。

    check_intersect_result const &sect = check_intersect( my_sphere, my_cone );
    

    これは戻り値をスライスしません。でなくても、正しいデストラクタが呼び出されvirtualます。でも、好きvirtualなら使えます。

    C++11 を使用すると、この問題は完全になくなりますauto。そうすれば、基本クラスさえ必要ありません。

    auto &&sect = check_intersect( my_sphere, my_cone );
    

    これは、ユーザーが関数を使用するために戻り値の型を知る必要がないため、まさに便利です。

  4. 単純な関数とメタ関数を分離することは、メンバーoperator()とを持つ包括的なクラスよりも優れていresult_typeます。拡張性については、モノリシック クラスを変更するよりも、新しいフリー関数とメタ関数の特殊化を追加する方が簡単です。

  5. intersection_resultなどのメタ関数を作成することは悪い考えではないかもしれませんが、intersection_result< sphere, cone >::type関数を呼び出すためだけにそれを要求することは避けたいと思います。

于 2013-05-12T02:47:34.150 に答える