Operator[][] overload

前端 未结 18 1853
轮回少年
轮回少年 2020-11-22 05:46

Is it possible to overload [] operator twice? To allow, something like this: function[3][3](like in a two dimensional array).

If it is pos

相关标签:
18条回答
  • 2020-11-22 06:38

    The shortest and easiest solution:

    class Matrix
    {
    public:
      float m_matrix[4][4];
    
    // for statements like matrix[0][0] = 1;
      float* operator [] (int index) 
      {
        return m_matrix[index];
      }
    
    // for statements like matrix[0][0] = otherMatrix[0][0];
      const float* operator [] (int index) const 
      {
        return m_matrix[index];
      }
    
    };
    
    0 讨论(0)
  • 2020-11-22 06:39
    template<class F>
    struct indexer_t{
      F f;
      template<class I>
      std::result_of_t<F const&(I)> operator[](I&&i)const{
        return f(std::forward<I>(i))1;
      }
    };
    template<class F>
    indexer_t<std::decay_t<F>> as_indexer(F&& f){return {std::forward<F>(f)};}
    

    This lets you take a lambda, and produce an indexer (with [] support).

    Suppose you have an operator() that supports passing both coordinates at onxe as two arguments. Now writing [][] support is just:

    auto operator[](size_t i){
      return as_indexer(
        [i,this](size_t j)->decltype(auto)
        {return (*this)(i,j);}
      );
    }
    
    auto operator[](size_t i)const{
      return as_indexer(
        [i,this](size_t j)->decltype(auto)
        {return (*this)(i,j);}
      );
    }
    

    And done. No custom class required.

    0 讨论(0)
  • 2020-11-22 06:39

    If, instead of saying a[x][y], you would like to say a[{x,y}], you can do like this:

    struct Coordinate {  int x, y; }
    
    class Matrix {
        int** data;
        operator[](Coordinate c) {
            return data[c.y][c.x];
        }
    }
    
    0 讨论(0)
  • 2020-11-22 06:39

    With a std::vector<std::vector<type*>>, you can build the inside vector using custom input operator that iterate over your data and return a pointer to each data.

    For example:

    size_t w, h;
    int* myData = retrieveData(&w, &h);
    
    std::vector<std::vector<int*> > data;
    data.reserve(w);
    
    template<typename T>
    struct myIterator : public std::iterator<std::input_iterator_tag, T*>
    {
        myIterator(T* data) :
          _data(data)
        {}
        T* _data;
    
        bool operator==(const myIterator& rhs){return rhs.data == data;}
        bool operator!=(const myIterator& rhs){return rhs.data != data;}
        T* operator*(){return data;}
        T* operator->(){return data;}
    
        myIterator& operator++(){data = &data[1]; return *this; }
    };
    
    for (size_t i = 0; i < w; ++i)
    {
        data.push_back(std::vector<int*>(myIterator<int>(&myData[i * h]),
            myIterator<int>(&myData[(i + 1) * h])));
    }
    

    Live example

    This solution has the advantage of providing you with a real STL container, so you can use special for loops, STL algorithms, and so on.

    for (size_t i = 0; i < w; ++i)
      for (size_t j = 0; j < h; ++j)
        std::cout << *data[i][j] << std::endl;
    

    However, it does create vectors of pointers, so if you're using small datastructures such as this one you can directly copy the content inside the array.

    0 讨论(0)
  • 2020-11-22 06:41

    It is possible if you return some kind of proxy class in first [] call. However, there is other option: you can overload operator() that can accept any number of arguments (function(3,3)).

    0 讨论(0)
  • 2020-11-22 06:42

    vector< vector< T > > or T** is required only when you have rows of variable length and way too inefficient in terms of memory usage/allocations if you require rectangular array consider doing some math instead! see at() method:

    template<typename T > class array2d {
    
    protected:
        std::vector< T > _dataStore;
        size_t _sx;
    
    public:
        array2d(size_t sx, size_t sy = 1): _sx(sx), _dataStore(sx*sy) {}
        T& at( size_t x, size_t y ) { return _dataStore[ x+y*sx]; }
        const T& at( size_t x, size_t y ) const { return _dataStore[ x+y*sx]; }
        const T& get( size_t x, size_t y ) const { return at(x,y); }
        void set( size_t x, size_t y, const T& newValue ) { at(x,y) = newValue; }
    };
    
    0 讨论(0)
提交回复
热议问题