5

私は、使用するデータ構造を除いて完全に同一の 4 つのアルゴリズムを実装しています — 2 つの use priority_queue、1 つの uses stack、および最後の uses queue。それらは比較的長いので、コンテナーの型をテンプレート引数として受け入れる関数テンプレートを 1 つだけ用意し、次のように、各アルゴリズムが適切な引数を使用してそのテンプレートを呼び出すようにしたいと考えています。

template <class Container>
void foo(/* args */)
{
    Container dataStructure;
    // Algorithm goes here
}

void queueBased(/* args */)
{
    foo<queue<Item> >(/* args */);
}

void stackBased(/* args */)
{
    foo<stack<Item> >(/* args */);
}

priority_queue- および -ベースの実装でこれを行うことができましたが、 -ベースのアルゴリズムでは別の名前を使用して最前の要素 (ではなく) にアクセスするためstack、同じことはできません。このケースに合わせてテンプレートを特殊化できることはわかっていますが、重複したコードが大量に発生することになります (これは避けたいことです)。queuefront( )top( )

これを達成するための最良の方法は何ですか? top( )私の最初の本能は、と同等の操作を追加する queue のラッパー クラスを作成することでしたがstack、STL クラスをサブクラス化することは禁止されていると読んでいます。では、どうすればこの動作を取得できますか?

4

5 に答える 5

7

コンテナー アダプターの型でオーバーロードされた非メンバーtop関数を作成できます。

template <typename T>
T& top(std::stack<T>& s) { return s.top(); }

template <typename T>
T& top(std::queue<T>& q) { return q.front(); }

// etc.

(テンプレート パラメーターを介して) コンテナー アダプターで別のシーケンス コンテナーを実際に使用する場合はSequence、それを処理するためにオーバーロードを適切に変更する必要があります。

std::vectorシーケンス アダプターの 1 つを使用するよりも、シーケンス コンテナー (例: ) を直接使用する方が簡単な場合があります。

于 2011-01-27T21:05:04.387 に答える
2

部分的な特殊化を使用して、正しい方法を選択できます。

template<class Container>
struct foo_detail {
  static typename Container::value_type& top(Container &c) { return c.top(); }
  static typename Container::value_type const& top(Container const &c) { return c.top(); }
};
template<class T, class Underlying>
struct foo_detail<std::queue<T, Underlying> > {
  typedef std::queue<T, Underlying> Container;
  static typename Container::value_type& top(Container &c) { return c.front(); }
  static typename Container::value_type const& top(Container const &c) { return c.front(); }
};

template<class Container>
void foo(/* args */)
{
    Container dataStructure;
    // Use foo_detail<Container>::top(dataStructure) instead of dataStructure.top().
    // Yes, I know it's ugly.  :(
}
于 2011-01-27T21:10:04.557 に答える
1

std::queue継承を使用せずにラッパーを作成できます。実際、ここでは継承は間違ったツールです。考えられる実装の 1 つを次に示します。queuequeue

template <typename QueueType>
class QueueWrapper {
public:
    explicit QueueWrapper(const QueueType& q) : queue(q) {
        // Handled in initializer list
    }

    typedef typename QueueType::value_type value_type;

    value_type& top() {
        return queue.front();
    }
    const value_type& top() const {
        return queue.front();
    }

    void pop() {
        queue.pop();
    }
private:
    QueueType queue;
};

お役に立てれば!

于 2011-01-27T21:04:15.047 に答える
0

queuepriority_queueおよびstackすべてコンテナー アダプターです。これらは、基になるコンテナーのラッパーです (デフォルトでは、fordequeおよびqueuefor ) 。stackvectorpriority_queue

vectordequeおよびlist(「実際の」コンテナ クラス) はほとんどのメソッドを共有しているため、仲介者をカットして代わりにそれらのクラスを使用できます。

また、公開継承は STL コンテナーには適していないことに注意してください。プライベート継承は問題ありません (そしておそらくあなたが望むものです)。

于 2011-01-27T21:03:35.613 に答える
-1

front()およびtop()は特定のタイプのコンテナーに固有ですが、すべてのSTLコンテナーはをサポートし*begin()ます。

于 2011-01-27T20:57:16.257 に答える