Гиперкуб с многомерными векторами - PullRequest
2 голосов
/ 20 декабря 2011

Я пытаюсь реализовать гиперкуб-класс, то есть многомерные векторы.У меня проблема с обобщением.Я могу сделать один для трехмерного гиперкуба, но, как уже упоминалось, проблема заключается в его обобщении.Кто-нибудь может мне помочь?Вы должны быть в состоянии написать hypercube<4> w(5), чтобы получить 4 измерения и 5 элементов в каждом векторе, что в общей сложности составляет 5 * 5 * 5 * 5 элементов.

Вот код, который я имею для трехмерной версии:

#include <vector>
using std::vector;

using namespace std;

template <int b> 
class Hypercube {
public:

Hypercube(int a) : intvec(a){
    for (int i = 0; i<a;i++) {
        intvec[i].resize(a);
        for (int j = 0;j<a;j++) {
            intvec[i][j].resize(a);
        }
    }
}
vector<vector<int> >& operator[](int i) {
    return intvec[i];
 }

vector<vector<vector<int> > > intvec;
};

Ответы [ 2 ]

2 голосов
/ 21 декабря 2011

Чтобы это работало, вам необходимо рекурсивное наследование для обеспечения правильного типа вектора и функции инициализации.Оба работают рекурсивно, для чего я создал небольшую вспомогательную структуру с именем hcube_info:

// hypercube.h
#include <vector>

template<unsigned N>
struct hcube_info;

template<>
struct hcube_info<1>
{ // base version
  typedef std::vector<int> type;
  static type init(unsigned innerdim, int value = 0){
      return type(innerdim, value);
  }
};

template<unsigned N>
struct hcube_info
{ // recursive definition, N dimensions
private:
  typedef hcube_info<N-1> base;
  typedef typename base::type btype;

public:
  typedef std::vector<btype> type;
  static type init(unsigned innerdim, int value = 0){
      return type(innerdim, base::init(innerdim, value));
  }
};

Как вы можете видеть, рекурсия полностью до одномерного базового случая.Нам также нужно рекурсивно инициализировать вектор для полного прохождения внутреннего измерения.

А теперь реальный класс, приятный интерфейс вокруг тестовой программы hcube_info:

template<unsigned N>
struct hypercube
{
private:
  typedef hcube_info<N> info;
  typedef typename info::type vec_type;

public:
  typedef typename vec_type::value_type value_type;
  typedef typename vec_type::size_type size_type;

  explicit hypercube(unsigned innerdim, unsigned value = 0)
    : c(info::init(innerdim, value))
  {
  }

  value_type& operator[](unsigned i){
    return c[i];
  }

  size_type size() const{ return c.size(); }

private:
  vec_type c;
};

:

#include "hypercube.h"
#include <iostream>

int main(){
  hypercube<4> c(5);
  unsigned s = c.size() * // dim 1
               c[0].size() * // dim 2
               c[0][0].size() * // dim 3
               c[0][0][0].size(); // dim 4
  std::cout << s << '\n'; // outputs: 625 -> 5 * 5 * 5 * 5 -> 5^4
}
0 голосов
/ 21 декабря 2011

Я бы предложил что-то в этом духе:

template <typename T, unsigned dim> class HQ {
  std::vector<HQ<T,(dim-1)> > vector;
  public:
    HQ(unsigned size) : vector(size,HQ<T,(dim-1)>(size)) {}
};

template <typename T> class HQ<T,1> {
  std::vector<T> vector;
  public:
    HQ(unsigned size) : vector(size,T()) {}
};

template <typename T> class HQ<T,0> {};

Затем вы можете реализовать свои средства доступа для первых обоих шаблонов, как хотите.Вы также можете сделать вещи немного проще и надежнее, допустив нульмерные матрицы:

template <typename T, unsigned dim> class HQ {
  std::vector<HQ<T,(dim-1)> > vector;
  public:
    HQ(unsigned size) : vector(size,HQ<T,(dim-1)>(size)) {}
};

template <typename T> class HQ<T,0> {
  T data;
  public:
    HQ(unsigned size) : data() {}
};

Я полагаю, что оператор доступа будет выглядеть примерно так:

template <typename T, unsigned dim> HQ<T,(dim-1)>& HQ<T,dim>::operator[](unsigned i) {
  return vector[i];
}
template <typename T, unsigned dim> HQ<T,(dim-1)> const& HQ<T,dim>::operator[](unsigned i) const {
  return vector[i];
}

так, что выможно написать

HQ<int,4> hq(5);
hq[1][4][2][0] = 77;
...