Operator[][] overload

前端 未结 18 1852
轮回少年
轮回少年 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:16

    An expression x[y][z] requires that x[y] evaluates to an object d that supports d[z].

    This means that x[y] should be an object with an operator[] that evaluates to a "proxy object" that also supports an operator[].

    This is the only way to chain them.

    Alternatively, overload operator() to take multiple arguments, such that you might invoke myObject(x,y).

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

    It 'll be great if you can let me know what function, function[x] and function[x][y] are. But anyway let me consider it as an object declared somewhere like

    SomeClass function;
    

    (Because you said that it's operator overload, I think you won't be interested at array like SomeClass function[16][32];)

    So function is an instance of type SomeClass. Then look up declaration of SomeClass for the return type of operator[] overload, just like

    ReturnType operator[](ParamType);

    Then function[x] will have the type ReturnType. Again look up ReturnType for the operator[] overload. If there is such a method, you could then use the expression function[x][y].

    Note, unlike function(x, y), function[x][y] are 2 separate calls. So it's hard for compiler or runtime garantees the atomicity unless you use a lock in the context. A similar example is, libc says printf is atomic while successively calls to the overloaded operator<< in output stream are not. A statement like

    std::cout << "hello" << std::endl;
    

    might have problem in multi-thread application, but something like

    printf("%s%s", "hello", "\n");
    

    is fine.

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

    It is possible to overload multiple [] using a specialized template handler. Just to show how it works :

    #include <iostream>
    #include <algorithm>
    #include <numeric>
    #include <tuple>
    #include <array>
    
    using namespace std;
    
    // the number '3' is the number of [] to overload (fixed at compile time)
    struct TestClass : public SubscriptHandler<TestClass,int,int,3> {
    
        // the arguments will be packed in reverse order into a std::array of size 3
        // and the last [] will forward them to callSubscript()
        int callSubscript(array<int,3>& v) {
            return accumulate(v.begin(),v.end(),0);
        }
    
    };
    
    int main() {
    
    
        TestClass a;
        cout<<a[3][2][9];  // prints 14 (3+2+9)
    
        return 0;
    }
    

    And now the definition of SubscriptHandler<ClassType,ArgType,RetType,N> to make the previous code work. It only shows how it can be done. This solution is optimal nor bug-free (not threadsafe for instance).

    #include <iostream>
    #include <algorithm>
    #include <numeric>
    #include <tuple>
    #include <array>
    
    using namespace std;
    
    template <typename ClassType,typename ArgType,typename RetType, int N> class SubscriptHandler;
    
    template<typename ClassType,typename ArgType,typename RetType, int N,int Recursion> class SubscriptHandler_ {
    
        ClassType*obj;
        array<ArgType,N+1> *arr;
    
        typedef SubscriptHandler_<ClassType,ArgType,RetType,N,Recursion-1> Subtype;
    
        friend class SubscriptHandler_<ClassType,ArgType,RetType,N,Recursion+1>;
        friend class SubscriptHandler<ClassType,ArgType,RetType,N+1>;
    
    public:
    
        Subtype operator[](const ArgType& arg){
            Subtype s;
            s.obj = obj;
            s.arr = arr;
            arr->at(Recursion)=arg;
            return s;
        }
    };
    
    template<typename ClassType,typename ArgType,typename RetType,int N> class SubscriptHandler_<ClassType,ArgType,RetType,N,0> {
    
        ClassType*obj;
        array<ArgType,N+1> *arr;
    
        friend class SubscriptHandler_<ClassType,ArgType,RetType,N,1>;
        friend class SubscriptHandler<ClassType,ArgType,RetType,N+1>;
    
    public:
    
        RetType operator[](const ArgType& arg){
            arr->at(0) = arg;
            return obj->callSubscript(*arr);
        }
    
    };
    
    
    template<typename ClassType,typename ArgType,typename RetType, int N> class SubscriptHandler{
    
        array<ArgType,N> arr;
        ClassType*ptr;
        typedef SubscriptHandler_<ClassType,ArgType,RetType,N-1,N-2> Subtype;
    
    protected:
    
        SubscriptHandler() {
            ptr=(ClassType*)this;
        }
    
    public:
    
        Subtype operator[](const ArgType& arg){
            Subtype s;
            s.arr=&arr;
            s.obj=ptr;
            s.arr->at(N-1)=arg;
            return s;
        }
    };
    
    template<typename ClassType,typename ArgType,typename RetType> struct SubscriptHandler<ClassType,ArgType,RetType,1>{
        RetType operator[](const ArgType&arg) {
            array<ArgType,1> arr;
            arr.at(0)=arg;
            return ((ClassType*)this)->callSubscript(arr);
        }
    };
    
    0 讨论(0)
  • 2020-11-22 06:24

    You can overload operator[] to return an object on which you can use operator[] again to get a result.

    class ArrayOfArrays {
    public:
        ArrayOfArrays() {
            _arrayofarrays = new int*[10];
            for(int i = 0; i < 10; ++i)
                _arrayofarrays[i] = new int[10];
        }
    
        class Proxy {
        public:
            Proxy(int* _array) : _array(_array) { }
    
            int operator[](int index) {
                return _array[index];
            }
        private:
            int* _array;
        };
    
        Proxy operator[](int index) {
            return Proxy(_arrayofarrays[index]);
        }
    
    private:
        int** _arrayofarrays;
    };
    

    Then you can use it like:

    ArrayOfArrays aoa;
    aoa[3][5];
    

    This is just a simple example, you'd want to add a bunch of bounds checking and stuff, but you get the idea.

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

    For a two dimensional array, specifically, you might get away with a single operator[] overload that returns a pointer to the first element of each row.

    Then you can use the built-in indexing operator to access each element within the row.

    0 讨论(0)
  • 2020-11-22 06:24
    #include<iostream>
    
    using namespace std;
    
    class Array 
    {
         private: int *p;
         public:
              int length;
              Array(int size = 0): length(size)
              {
                    p=new int(length);
              }
              int& operator [](const int k)
              {
                   return p[k];
              }
    };
    class Matrix
    {
          private: Array *p;
          public: 
                int r,c;
                Matrix(int i=0, int j=0):r(i), c(j)
                {
                     p= new Array[r];
                }
                Array& operator [](const int& i)
                {
                     return p[i];
                }
    };
    
    /*Driver program*/
    int main()
    {
        Matrix M1(3,3); /*for checking purpose*/
        M1[2][2]=5;
    }
    
    0 讨论(0)
提交回复
热议问题