【问题标题】:Overloading operator [] for N-dimensional structureN维结构的重载运算符[]
【发布时间】:2023-03-25 11:40:01
【问题描述】:

我用向量和模板制作了一个 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&amp; operator[](unsigned i) 的用途。

但是,唉,不要这样工作。而且我无法弄清楚它会如何

编辑别担心,我不会访问空内存,结构是初始化和填充的,只是为了清楚起见,我没有包含代码。

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

【问题讨论】:

  • 与您的问题无关,但这是一种在内存中布置数据的可怕方式。你最终得到了无数的动态分配和间接。拥有一个连续的内存空间并以多维的方式处理它通常会好得多。
  • 我不明白你在做什么。您有几个堆叠的向量,并且您想通过单个 int 参数访问它。实现返回T::value_typeoperator()(size_t ... I)不是更好吗?
  • @KerrekSB 我只是想不出任何更好的结构,我事先不知道尺寸。欢迎推荐更好的,不胜感激
  • @TeaOverflow:这个想法是分配一次内存来保存N1*N2* ... * Ndim 值,然后通过索引i1+N1*(i2+N2*(... + idim) ) 访问您的条目[i1][i2] ... [idim]。例如,在 2D 中,不使用 std::vector&lt;std::vector&lt;double&gt; &gt;(N1,std::vector&lt;double&gt;(N2)),而是使用 std::vector&lt;double&gt;(N1*N2)

标签: c++ templates operator-overloading


【解决方案1】:

让编译器推导出返回类型的方式是auto:

在 C++14 中:

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

在 C++11 中:

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

【讨论】:

  • 非常简单。谢谢。
【解决方案2】:

我正在回复你的评论

欢迎推荐更好的,不胜感激。

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

#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

但正如我所写,大括号很烂,所以我会使用可变参数模板重写整个内容。

【讨论】:

    【解决方案3】:

    您的方法的问题是您没有初始化向量内的任何内存,而只是试图返回不存在的内存点。以下内容(WARNING: uncleaned and unrefactored code ahead):

    #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:以多维数组方式访问的连续内存空间将被证明更快,而且肯定更易于维护/更易于使用和阅读。 p>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多