4

それで、私はしばらくの間私を追ってきた次の問題を抱えています。

Shaderは頂点のグループを描画します。これはテキスト ファイルから GPU に読み込まれるため、OpenGLでは入力する必要がまったくありません

struct Shader
{
    // Load that shader from filename
    Shader( string filename ... ) ;
} ;

頂点のグループがコードに入力されています

VertexArray<VertexPTC> ptcVerts ; // PTC is position, texcoord, color.

の配列は、によってptcVerts のみ描画されますptcShader。の配列pcVertsを aで描画しようとするとptShaderエラーになります (色の値が texcoords として解釈されるため)。

したがって、コンパイラにそのようなエラーにフラグを付けてもらいたいと思います。方法は次のとおりです。

template<typename T> struct Shader

現在、シェーダーはまったく使用Tされていませんが、コンパイル時に型付けされます。コンパイラは、 aVertexArray<VertexPTC>によって描画されるという制限を適用するようになりましたShader<VertexPTC>

これは良いですか悪いですか?Shaderは を必要とせず、使用しないTので、私のテンプレートの使用はどういうわけか誤用ではないかと心配しています。

4

3 に答える 3

2

コードで現実世界の制約を表現しています。ここでのあなたの例は、実際にここで何かを買うことを示していないので、証拠を続けると、それを表現するのは冗長なのか、それとも実際に発生する状況とは無関係なのか疑問に思います. しかし、さまざまな種類の頂点データセットに対してさまざまな種類のシェーダーを使用する場合は、ここでこれを表現する正確な方法を見つけたと思います。

于 2013-04-24T19:02:13.893 に答える
2

誤用です。テンプレートの使用は無料ではありません。そこでテンプレートを使用する利点のために、処理したいクラスをテンプレート化すると、さらに困難が生じます。

後で a -- を処理するための一般的な方法が必要になったときに、これで問題が発生しましたShader-- 最後の bound を無効にする方法が必要でしたが、Shaderそれがどのタイプであるかは問題ではありませんでした。

派生元のサブクラスを人為的に考慮するか、シェーダー クラスからShader<T>テンプレート パラメーターを削除する必要がありました。T

しかし、実際にはもっと良い方法を見つけました。通常どおりクラスを定義するだけです。

struct Shader
{
  // complete, untemplatized definition.  If it doesn't use T
  // internally, THEN DO NOT INTRODUCE ARTIFICIAL DEPENDENCE ON T!
} ;

しかし、私は次のように定義します。

template <typename T> struct TShader : public Shader { } ;

SO今、コンパイラに型を強制させたいときTShader<T>は、2番目の定義を使用してください。型を適用するためにコンパイラが必要ない場合は、完全に機能する基本クラスShader定義を使用してください。

これにより、両方の長所が得られます。必要に応じて、 をテンプレート化されていない基本クラスとしていつでも扱うことができますTShader<T>。機能を失うことも、不要な抽象インターフェイスを作成することもありません。

于 2013-07-07T20:48:17.753 に答える
0

コンパイラに間違ったことをさせたくない場合、1 つの方法は次のようにすることです。

class ShaderPTC
{
public:
   ShaderPTC( string filename, <other params> );
   void Draw( VertexArray<VertexPTC>& Vertices );
   ~ShaderPTC();
private:
   Shader m_shader;
}

class ShaderPC
{
public:
   ShaderPC( string filename, <other params> );
   void Draw( VertexArray<VertexPC>& Vertices );
   ~ShaderPC();
private:
   Shader m_shader;
}

コンストラクターが適切なシェーダーを内部で作成し、このクラスのオブジェクトをポインター/参照によって渡すようにして、ラップされたシェーダーのコピーを気にする必要がないようにします (コピー コンストラクター/割り当てもプライベートにする必要がある場合があります)。 .

関数はDraw正しいタイプの頂点配列のみを受け入れ、内側のシェーダーは公開されていないため、間違ったパラメーターを渡すことはできません。

コンストラクターで記述する必要があるコードとDraw関数が汎用的である場合は、これをテンプレート クラスにすることができます。それ以外の場合は、とにかくテンプレートを特殊化する必要があり、テンプレート アプローチに実際の利点はありません。

変数に正しく名前を付けることでこのような問題を防ぐことができますが、変数を正しく入力すると、問題を解決するのがはるかに難しくなります。

于 2013-04-24T19:28:42.950 に答える