モジュール性と単純さが互いに矛盾しているように見える特定のインスタンスに出くわしました。通常はそうではないので、どうすれば解決できるのかよくわかりませんでした。
queue
インターフェースを作成したいとします。
_template<typename T>
class queue {
public:
virtual ~queue() {}
virtual void enqueue(const T& t) = 0;
virtual void enqueue(T&& t) = 0;
virtual T dequeue() = 0;
};
_
いくつかの実装(一部はアトミック)を作成しているときに、empty()
またはfull()
メソッドを呼び出す「抽象クラス」を使用することで時間を大幅に節約できることに気付きました。条件変数の実装に役立ちます。そうすれば、私が実装する同期クラスは、その「抽象クラス」を拡張することもできます。次に、抽象クラスは拡張インターフェースを実装しました。
_template<typename T>
class bounded_queue : public queue<T> {
public:
virtual ~bounded_queue() {}
virtual bool full() = 0;
virtual bool empty() = 0;
};
_
しかし、これらのメソッドをqueue
に押し込んだだけで、おそらくデフォルトでfalse
を返すとしたら、もっと簡単ではないでしょうか。この質問への答えは私にはすぐにはわかりません。そうである場合は、 スペクトルのもう一方の端 を検討してください。
上記のデザイン(リンク内)が期待どおりに機能するかどうかさえわかりません!シンプルでありながらモジュール式のものを決定するにはどうすればよいですか?
それらは同じインターフェースにある必要があります。有界vs非有界はこれを変更しません。簡単な解決策は、サブクラスがオーバーライドできるisfull()とisempty()のデフォルトの実装を提供することです。 [私の答えは@ tp1のコメントとほとんど同じです。]
Empty()を指定しない場合、呼び出し元はデキューを要求するかどうかをどのように判断できますか?
Peek()を含めることも検討する必要があります。 isempty()を実装すると、dequeue()とpeek()の両方が、空のキューで呼び出された場合に例外をブロックまたは発生させることができます。
一般的な代替手段は、いくつかの異なるタイプのキューを提供することです。この場合、ブロッキングキューは別のクラスである可能性がありますが、インターフェイスは同じです。ただし、isfull()が真になることのない無限キューには同じことが当てはまりません。