-1

Im trying to get better at C++ by coding up a class for a vector like object.

I wish for it to have an operator overloading for [], that takes in an std::initializer_list<int> for input of indices on underlying array, and returns a reference to those elements of the array.

So something like this would be possible:

MyVector arr = {1, 2, 3, 4};

arr[{0, 2}] = 3;
// or 
arr[{0, 2}] = {5, 6};

What I've thought of is to create another class that inherits MyVector, and write an assignment operator for this class

MyVector::operator[](std::initializer_list<int> ind){
    return MyVectorRef(this, ind);
}

class MyVectorRef: private MyVector{
   MyVector* base;
   std::initializer_list<int> indices;

   MyVectorRef(MyVector* base, ind): base(base), indices(ind) {};

   MyVector operator=(std::initializer_list<int> cp){
      for(int i: indices){
          (*base).data[i] = cp[i];
      }
   }
   // similarly for the first case...
};

I know this is very hacky, maybe wont even work. Also, may be of some problem if i wish to have method cascading.

Is there a better way to work around this?

genpfault
  • 51,148
  • 11
  • 85
  • 139
  • 1
    I’m voting to close this question because it belongs int the [Code Review](https://codereview.stackexchange.com/) Stack Exchange. – Jan Schultke Aug 10 '23 at 16:39
  • Not sure it's suitable for code review. The asker's not even sure it works. Code review is for stuff that works, but could work *better*. – user4581301 Aug 10 '23 at 17:54
  • It sounds like you're trying to implement "slicing" for C++ [std::vector](https://en.cppreference.com/w/cpp/container/vector). Look here: https://www.geeksforgeeks.org/slicing-a-vector-in-c/ and here: https://stackoverflow.com/a/58724503/421195 – paulsm4 Aug 10 '23 at 19:56
  • Are you looking for `std::span` maybe? – Jesper Juhl Aug 10 '23 at 20:51
  • Thanks all for your efforts, but my question was aimed at getting to access the references to elements at differernt indices, so the links mentioned by @paulsm4 dont help as much. Also, std::span, wont work, because it requires data to be contiguous in memory. Thanks for introducing it to me though! – DANISH ANGURAL Aug 11 '23 at 16:45

1 Answers1

1

A few issues: Your function signature for operator[] is incorrect: it should be MyVectorRef MyVector::operator[](std::initializer_list<int> ind), as C++ doesn't allow you to omit the return type for operator[].

If you declare MyVectorRef under operator[], when C++ compiles the line MyVectorRef operator[](...), C++ doesn't recognize what MyVectorRef is, so it throws an error. To solve this, you have to add an incomplete class declaration for MyVectorRef above MyVector.

So something like this:

class MyVectorRef; //incomplete class declaration for MyVectorRef

class MyVector {
   //...

   MyVectorRef operator[](std::initializer_list<int> ind); //method declaration for operator[]
};

class MyVectorRef {
   MyVector* base;
   std::initializer_list<int> indices;
   //...

}; //complete definition of MyVectorRef

MyVectorRef MyVector::operator[](std::initializer_list<int> ind) {
   return MyVectorRef(this, ind);
}

The reason for the incomplete class declaration is essentially to tell the compiler that the token MyVectorRef exists, so that when the compiler compiles the method declaration for operator[], it knows that MyVectorRef is a class.

azhen7
  • 371
  • 1
  • 5
  • Thanks for answering! Although my question was aimed at finding a way around this hack with some other, more stable functionality. – DANISH ANGURAL Aug 11 '23 at 16:48
  • As far as I know using `MyVectorRef` is the best approach. Maybe it isn't but I can't think of another one. – azhen7 Aug 11 '23 at 19:48