为N维结构重载operator []

时间:2014-09-28 11:13:12

标签: c++ templates operator-overloading

我用矢量和模板制作了一个N维结构:

//----------------N-dimensional vector--------------------------------
template<int dim,typename T> class n_dim_vector {

public:
    typedef std::vector<typename n_dim_vector<dim - 1, T>::vector> vector;
};

template<typename T> class n_dim_vector <0, T> {

public:
    typedef T vector;
};

它可以使用不同的维度计数进行实例化,并且是表示搜索空间的类的prt。

template<int dim, typename T> class n_dim_ssc {

private:
    typename n_dim_vector<dim, T>::vector searchspace;

};

我的问题:我无法operator[]正确访问searchspace,特别是返回类型。

我试过了:

template<typename V> std::vector<V>& operator[](unsigned i) {
    return searchspace[i];
}

T& operator[](unsigned i) {
    return searchspace[i];
}

首先,认为编译器会将typename V派生为除最后一级以外的所有类型searchspace。这就是T& operator[](unsigned i)的用途。

但是,唉,不要这样做。我无法弄清楚它会如何

编辑不要害怕,我不会访问空白内存,结构已初始化并填充,我只是为了清晰起见而没有包含代码。

另外,我不打算用一个整数访问它,我想使用searchspace[i][j]..[k]

3 个答案:

答案 0 :(得分:2)

让编译器推断出返回类型的方法是auto

在C ++ 14中:

auto operator[](unsigned i) { return searchspace[i]; }

在C ++ 11中:

auto operator[](unsigned i) -> decltype(searchspace[i]) { return searchspace[i]; }

答案 1 :(得分:1)

我正在回答你的评论

  

随意推荐更好的东西,我很感激。

以下代码显示了一种处理多维向量的方法,即非递归。它可以通过几种方式进行改进,我现在没有考虑过(例如,我不想使用和传递那么多数组,而是使用可变参数列表。但是这需要更多更多的难度代码,所以我让它成为。)

#include <numeric>

template<size_t Dim, typename T>
struct MultiDimVector
{
    std::array<size_t, Dim> Ndim;
    std::array<size_t, Dim> stride;
    std::vector<T> container;

    MultiDimVector(std::array<size_t, Dim> const& _Ndim) : Ndim(_Ndim), container(size())
    {
        stride[0] = 1;
        for (size_t i = 1; i<Dim; ++i)
        {
            stride[i] = stride[i - 1] * Ndim[i - 1];
        }
    }

    size_t size() const
    {
        return std::accumulate(Ndim.begin(), Ndim.end(), 1, std::multiplies<size_t>());
    }

    size_t get_index(std::array<size_t, Dim> const& indices) const
    {
        //here one could also use some STL algorithm ...
        size_t ret = 0;
        for (size_t i = 0; i<Dim; ++i)
        {
            ret += stride[i] * indices[i];
        }
        return ret;
    }

    T const& operator()(std::array<size_t, Dim> const& indices) const
    {
        return container[get_index(indices)];
    }
};

您可以像

一样使用它
MultiDimVector<3, double> v({ 3, 2, 5 });   //initialize vector of dimension 3x2x5
auto a = v({0,1,0});                        //get element 0,1,0

但是正如我写的那样,大括号很糟糕,所以我会使用可变参数模板重写整个事物。

答案 2 :(得分:0)

你的方法的问题是你没有初始化向量内的任何内存,只是试图返回不存在的内存点。以下内容中的内容(警告:前面未清除和未重构的代码):

#include <iostream>
#include <vector>

template<int dim,typename T> class n_dim_vector {

public:
    typedef std::vector<typename n_dim_vector<dim - 1, T>::vector> vector;
};

template<typename T> class n_dim_vector <0, T> {

public:
    typedef T vector;
};

template<int dim, typename T> class n_dim_ssc {

public:
    typename n_dim_vector<dim, T>::vector searchspace;

    n_dim_ssc() {}
    n_dim_ssc(typename n_dim_vector<dim, T>::vector space) : searchspace(space) {}

    n_dim_ssc<dim-1, T> operator[](std::size_t i) {

        if(searchspace.size() < ++i)
            searchspace.resize(i);
        return n_dim_ssc<dim-1, T>(searchspace[--i]);
    }

    typename n_dim_vector<dim, T>::vector get() {
        return searchspace;
    }

};

template<typename T> class n_dim_ssc<0,T> {

public:
    typename n_dim_vector<0, T>::vector searchspace;

    n_dim_ssc() {}
    n_dim_ssc(typename n_dim_vector<0, T>::vector space) : searchspace(space) {}

    typename n_dim_vector<0, T>::vector get() {
        return searchspace;
    }
};



int main(int argc, char** argv) {
  n_dim_ssc<0, int> ea;
  int a = ea.get();

  n_dim_ssc<1, int> ea2;
  auto dd2 = ea2[0].get();

  n_dim_ssc<2, int> ea3;
  auto dd3 = ea3[0][0].get();
}

Try it out

将使用访问器方法(您可以根据需要进行修改)。

无论如何我非常同意Kerrek :以多维数组方式访问的连续内存空间将被证明更快,更可维护/更容易使用和阅读。