2

数値の配列を表すテンプレートクラスがあります。

このクラスは、任意のタイプの数値(int、doubleなど)と3つのタイプのコンテナー(std :: vector、std :: deque、およびstd :: list)で機能するようにします。

これが私の特定の問題に関連する実装のビットです:

template < typename Numeric_t, typename Container = std::vector<Numeric_t> >
class Array {

  // field member
  Container m_data;

  // other stuff here
  // ...

  // random element access for std::vector and std::deque
  Numeric_t & operator[] (unsigned int index) { return m_data[index]; }

  // random element access for std::list
  Numeric_t & operator [] (unsigned int index) {
    std::list<Numeric_t> :: iterator it = m_data.begin();
    std::advance(it, index);
    return *it;
  }

}

もちろん、コンパイラーでは、演算子[]をオーバーロードすることはできません。

私が必要とするのは、 std :: listに固有の演算子[]の一種の部分的な特殊化ですが、C++でも部分的なテンプレート関数の特殊化は許可されていません。

(ランダム要素アクセスはリストにとって効率的ではないことを私は知っていますが、それはここでのポイントではありません)。

理想的には、クライアントコードで次のようにArrayクラスを使用したいと思います。

Array < int, std::vector<int> > vec;
Array < int, std::list<int> >   lst;

// fill arrays here
// ...

std::cout << vec[0] << std::endl;
std::cout << lst[0] << std::endl;

多くの調査の後、私は実用的な解決策を見つけることができませんでした。

この問題を解決するための最もエレガントな方法は何でしょうか?

ご協力いただきありがとうございます。

4

1 に答える 1

1

明確な解決策は、完全なクラス テンプレートの特殊化を使用することです。共通のコードを共有するために、1 つの共通の基本クラスからさまざまな特殊化を派生させることができます。

ArrayBase特定のコンテナー タイプに依存せず、コンテナーへのアクセスを許可するすべてのコードを含むクラスを、保護するか、フレンド クラスを作成することによって作成しますArray

template <class Numeric_t, class Container>
class Array
  : public ArrayBase<Numeric_t, Container>
{
  // Container specific code, generic version that works for all containers.
};

template <class Numeric_t>
class Array<Numeric_t, std::vector<Numeric_t>>
  : public ArrayBase<Numeric_t, std::vector<Numeric_t>>
{
  // Optimized code for std::vector.
}

別のアプローチ: コードを含む静的メンバー関数を記述してidx、コンテナーの -th エントリにアクセスし、その関数を特殊化することもできます。

template <class Numeric_t, class Container>
class Array
{
  template <class Cont>
  static Numeric_t get(Cont const& container, unsigned int idx)
  {
    std::list<Numeric_t>::iterator it = container.begin();
    std::advance(it, idx);
    return *it;
  }

  template <>
  static Numeric_t get(std::vector<Numeric_t> const& container, unsigned int idx)
  {
    return container[idx];
  }

  public:
    Numeric_t operator[](unsigned int idx) const { return get(m_data, idx); }
};

申し訳ありませんが、これは機能しません。静的メンバー関数を特殊化できないことを忘れていました...もう一度。

別の方法として SFINAE を使用することもできますが、これは非慣用的な使用法であり、この場合はお勧めしません。

于 2012-04-18T07:04:23.430 に答える