7

質問をするのがいかに難しいかを理解しています...うまくいけば、問題を実証するのに十分正確で、すべてを台無しにしないのに十分短い例を示すことができます...少なくとも編集する可能性があります。

ですから、これは今の私の状況のようなものです。もちろん、私の質問の本質に焦点を当てようとして、論理/構造の観点から(そしてとにかく命名の観点から)それを少し変更しました:

// MyClass deals with lists (actually several data structures) of the
// type MyType which should support different types and has to be 
// efficiently dealt with. Templating seems just right here
class MyClass
{
  ...

  void doSomething<class MyType>(vector<MyType> someList);

  ...

  // At some point I have to extract elements of the type MyType.
  // The extractor obviously depends on MyType but it is not possible to
  // Create a general version that could use templates itself 
  // (unless I use a specialization for each possible MyType)

  // I am stuck between these two alternatives:

  // Possibility1:
  // Let the client pass the right extractor and template it.
  template<class Extractor, class MyType>
  void extract(const Extractor& extractor, const string& source, 
               vector<MyType>* dest)
  {
     extractor.extract(source, dest);
  }

  // Possibility2:
  // Use a member _extractor of some base type that has to be set
  // to a specialization. The ExtractorBase has a virtual method
  // template<T> void extract(const string& source, vector<T>* myType) = 0
  // with no definition that is only defined in subclasses wrt certain
  // postings.
  ExtractorBase _extractor;

  template<class MyType>
  void extract(const string& source, vector<MyType>* dest)
  {
     _extractor.extract(source, dest);
  }
}

現時点では、possible1をお勧めします。これは、将来試してみたいMyTypeのすべてのバリアントと関連するExtractorについて、Extractorの継承をいじる必要がないためです。

一方、エクストラクタには、複雑なコードといくつかのメンバー(特定の入力を特定の値にマップする巨大なマップのようなもの)が必要になる場合があります。したがって、テンプレートを使用してもパフォーマンスは向上しません。特にヘッダーファイルのみを使用する場合、エクストラクターと、おそらくインライン化されるはずのファンクターでさえ、問題外です。これまで、これは、テンプレートを使用するとコードの複雑さが増すだけであり(インスタンス化に対処する必要がある、クライアントコードの処理が困難になるなど)、それを完全に回避する必要があることを強く示しています。

それとも、私がまったく考えていなかった3番目の可能性がありますか?

4

4 に答える 4

2

最初のオプションを選択することをお勧めします。それはよりきれいで維持可能です。

あなたのコメントから、私はあなたが2番目のオプションについて間違った仮定をしていることを理解しています:

// The ExtractorBase has a virtual method
// template<T> void extract(const string& source, vector<T>* myType) = 0;

いいえ。それは可能ではありません; template関数を。にすることはできませんvirtual。したがって、2番目のオプションを実装するには、汚くて保守が難しい方法を選択する必要がありますが、これはお勧めできません。

于 2011-07-06T09:19:08.883 に答える
1

私は最初の可能性をより柔軟だと考えています。

2番目の可能性では、クラスメンバーとして不要なカプセル化エクストラクタの関心がわかりません。また、MyClassとExtractorの間の結合が増えますが、これは良いことではありません。テンプレートを作成すると、(何らかの方法で)結合度が低下するため、選択肢がある場合は、より良い方法です。

于 2011-07-06T08:49:47.800 に答える
1

3番目のオプションがあり、MyTypeから自分自身を構築する方法を知っているコンストラクターを提供しますstd::string。または、イテレータのペアを使用することをお勧めします。したがってMyType、文字列からsのシーケンスを作成する必要がある場合は、範囲を使用できます。

于 2011-07-06T08:50:33.647 に答える
0

これは、ストラテジーパターンの場合のように聞こえます。クラスには、実装が異なる可能性のある操作があります。

これが、さまざまなアプローチで見られるトレードオフです。

テンプレートソリューションでは、抽象インターフェイスクラスを宣言したり、を使用しvtblて使用する実装を特定したりする必要がなくなります。ただし、コンパイル時にアプリケーションにロックする必要があります。

継承ソリューションでは、抽象インターフェイスクラスを宣言する必要があり、パフォーマンスにvtbl. 影響を与えて実装を検索しますが、実行時に抽出実装を選択できます。

アプリケーションにとってパフォーマンスがどれほど重要で、どれだけ柔軟である必要があるかわからないので、抽象クラスでインターフェイスを定義してそれにコーディングすることの明確さが好きなので、おそらく継承ソリューションを選択します。

于 2011-07-06T14:51:41.917 に答える