Hypercube with multidimensional vectors

后端 未结 2 1426
星月不相逢
星月不相逢 2021-01-15 14:20

I\'m trying to implement a hypercubeclass, that is, multidimensional vectors. I have a problem generalizing it. I\'m able to make one for a three dimensional hypercube, but

相关标签:
2条回答
  • 2021-01-15 14:44

    For this to work, you need recursive inheritence to provide the correct vector type and the initialization function. Both work recursively, for which I created a little helper struct called 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));
      }
    };
    

    As you can see, recursion all the way to the one dimensional base case. We also need to recursively initialize the vector to pass the inner dimension all the way through.

    And now the real class, a nice interface around the 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;
    };
    

    Test program:

    #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 讨论(0)
  • 2021-01-15 15:02

    I would suggest something along those lines:

    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> {};
    

    You can then implement your accessors for the first both templates as you wish. You can also make things a bit more simple and robust by allowing zero-dimensional matrices:

    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() {}
    };
    

    I imagine an access operator would look something like this:

    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];
    }
    

    such that you can write

    HQ<int,4> hq(5);
    hq[1][4][2][0] = 77;
    
    0 讨论(0)
提交回复
热议问题