我正在移植使用大量浮点数的代码,这可能会导致malloc从c到c++的失败。我问了一个问题,我应该使用 vector 还是双端队列,Niki Yoshiuchi慷慨地为我提供了一个安全包装类型的示例:

template<typename T>
class VectorDeque
{
private:
  enum TYPE { NONE, DEQUE, VECTOR };
  std::deque<T> m_d;
  std::vector<T> m_v;
  TYPE m_type;
  ...
public:
  void resize(size_t n)
  {
    switch(m_type)
    {
      case NONE:
      try
      {
        m_v.resize(n);
        m_type = VECTOR;
      }
      catch(std::bad_alloc &ba)
      {
        m_d.resize(n);
        m_type = DEQUE;
      }
      break;
    }
  }
};

我需要二维 vector /双端队列的 vector ,因此将其修改为以下代码:
template<typename T>
class VectorDeque
{
private:
  enum STORAGE_CONTAINER { NONE, DEQUE, VECTOR };
  std::deque<std::deque<T> > x_d,y_d,z_d;
  std::vector<std::vector<T> > x_v,y_v,z_v;
  TYPE my_container;
public:
  void resize(size_t num_atoms, size_t num_frames)
  {
    switch(m_type)
    {
      case NONE:
      try
      {
        x_v.resize(num_atoms);
 for (unsigned int couter=0;couter < num_frames; counter++)
   x_v[counter].resize(num_frames);
        y_v.resize(num_atoms);
 for (unsigned int couter=0;couter < num_frames; counter++)
   y_v[counter].resize(num_frames);
        z_v.resize(num_atoms);
 for (unsigned int couter=0;couter < num_frames; counter++)
   z_v[counter].resize(num_frames);
        my_container = VECTOR;
      }
      catch(std::bad_alloc &e)
      {
        x_d.resize(num_atoms);
 for (unsigned int couter=0;couter < num_frames; counter++)
   x_d[counter].resize(num_frames);
        y_d.resize(num_atoms);
 for (unsigned int couter=0;couter < num_frames; counter++)
   y_d[counter].resize(num_frames);
        z_d.resize(num_atoms);
 for (unsigned int couter=0;couter < num_frames; counter++)
   z_d[counter].resize(num_frames);
        my_container = DEQUE;
      }
      break;
    }
  }
};

现在,我希望能够定义方括号运算符,这样我就可以像x[1][2]直接访问我正在使用的实际内存容器中的任何一个(由我的枚举变量的值给出。

我已经看到了一些有关覆盖括号运算符的教程,但是肯定不知道覆盖双括号。

如何使双括号过载?

此外,您将如何重载双迭代器(以防我想使用迭代器而不是直接索引)?

编辑1:

基于Martin York / Matteo Italia的解决方案,我设计了以下类(class):
template<typename T>
class VectorDeque2D
{
public:

  class VectorDeque2D_Inner_Set
  {
    VectorDeque2D& parent;
    int   first_index;
  public:
    // Just init the temp object
    VectorDeque2D_Inner_Set(My2D& p, int first_Index) :
      parent(p),
      first_Index(first_index) {}
    // Here we get the value.
    T& operator[](int second_index)  const
    { return parent.get(first_index,second_index);}
  };

  // Return an object that defines its own operator[] that will access the data.
  // The temp object is very trivial and just allows access to the data via
  // operator[]
  VectorDeque2D_Inner_Set operator[](unsigned int first_index) {
    return (*this, x);
  }


  void resize_first_index(unsigned int first_index) {
    try {
      my_vector.resize(first_index);
      my_container = VECTOR;
    }
    catch(std::bad_alloc &e) {
      my_deque.resize(first_index);
      my_container = DEQUE;
    }
  }

  void resize_second_index(unsigned int second_index) {
    try {
      for (unsigned int couter=0;couter < my_vector.size(); counter++) {
    my_vector[counter].resize(second_index);
      }
      my_container = VECTOR;
    }
    catch(std::bad_alloc &e) {
      for (unsigned int couter=0;couter < my_deque.size(); counter++) {
    my_deque[counter].resize(second_index);
      }
      my_container = DEQUE;
    }
  }
  void resize(unsigned int first_index,
          unsigned int second_index) {
    try {
      my_vector.resize(first_index);
      for (unsigned int couter=0;couter < my_vector.size(); counter++) {
    my_vector[counter].resize(second_index);
      }
      my_container = VECTOR;
    }
    catch(std::bad_alloc &e) {
      my_deque.resize(first_index);
      for (unsigned int couter=0;couter < my_deque.size(); counter++) {
    my_deque[counter].resize(second_index);
      }
      my_container = DEQUE;
    }
  }
private:
  enum STORAGE_CONTAINER { NONE, DEQUE, VECTOR };

  friend class VectorDeque2D_Inner_Set;

  std::vector<std::vector<T> > my_vector;
  std::deque<std::deque<T> > my_deque;
  STORAGE_CONTAINER my_container;

  T& get(int x,int y) {
    T temp_val;
    if(my_container == VECTOR) {
      temp_val = my_vector[first_index][second_index];
    }
    else if(my_container == DEQUE) {
      temp_val = my_deque[first_index][second_index];
    }

    return temp_val;
  }

};

最后是尺寸安全的2D容器!!谢谢你们!

最佳答案

主要技术有两种:

1)使用operator()而不是operator []。
这是因为operator()允许多个参数。

class My2D
{
    public:
       int&   operator()(int x,int y)  { return pget(x,y);}
    private:
       int&   pget(int x,int y) { /* retrieve data from 2D storage */ }
};

2)使用operator [],但返回一个中间对象。
然后,您可以将第二个operator []应用于中间对象。
class My2D
{
    public:
       class My2DRow
       {
           My2D& parent;
           int   x;
           public:
               My2DRow(My2D& p, int theX) : parent(p), x(theX) {}     // Just init the temp object
               int& operator[](int y)  const { return parent.pget(x,y);}   // Here we get the value.
       };

       // Return an object that defines its own operator[] that will access the data.
       // The temp object is very trivial and just allows access to the data via operator[]
       My2DRow operator[](int x)        { return My2DRow(*this, x);}
    private:
       friend class My2DRow;
       int&   pget(int x,int y) { /* retrieve data from 2D storage */ }
};

int main()
{
    My2D   data;
    int&   val = data[1][2]; // works fine.

    // This is the same as
    My2D::My2DRow row  = data[1];
    int&          val2 = row[2];
}

我更喜欢第二种技术。
这是因为它使原始代码保持不变,并且在数组上下文中更自然地读取。当然,您需要为实现2D数组的稍微复杂的代码付出高水平的简单性。

关于c++ - 如何定义类似于Vector的Vector的Double Brackets/Double Iterator运算符?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48403569/

10-11 00:25
查看更多