-2

Yes I know it sounds weird, but I'm looking for a way to overwrite the indirection operator to return another class object. Let me explain better:

In main.cpp I got

MyInt *V = new MyInt[10];
(*V)[3]=10;

but I would like to have it like:

MyInt *V = new MyInt[10];
V[3]=10;

In MyInt.h I've used a wrapper to catch and remove the square brackets of MyInt class and then overload the "=" operator. That's because I need a class that could store the vector and also a counter of its usage inside it. More details here.

MyInt.h

wrapper operator[] ( std::size_t i ) { return wrapper( *this, i ) ; }

The work flow is "MyInt::wrapper::operator=". Now it works but I would like to get rid of (*V). Would be possible to remove it by overloading the indirection operator to return a wrapper object that could be passed to "wrapper::operator=" then? I was thinking something like:

MyInt& operator*(){
    return wrapper(*this)
}

but it doesn't work, I get "error: invalid initialization of non-const reference of type ‘MyInt&’ from an rvalue of type ‘test::wrapper’". I know that the indirection operator should return the same class, but I really need it that way. Any suggestion? Thanks in advance.

Opaco
  • 3
  • 2
  • So, you would like `MyInt V = new MyInt[10];` to compile? If so, that's easy. Sure that's what you want? `V` wouldn't know how many elements it's pointing at though. – Ted Lyngmo Oct 14 '22 at 15:32
  • 1
    `(*V)[3] = 10;` is calling `operator[]` of the first in your array of 10 `MyInt`s to get *something*, and then calling that *something*s `operator=(int)`. Is that what you want? `V[3]=10;` looks more normal, in that you are calling `operator=(int)` on the forth `MyInt` – Caleth Oct 14 '22 at 15:35
  • 1
    Just to make sure: you want `V` to be an array of 10 `MyInt`s (and not to make one `MyInt` calling constructor taking single `int`)? – Yksisarvinen Oct 14 '22 at 15:36
  • 1
    With the new syntax, you're not specifying _which_ of the 10 `MyInt`s you're acting on. You have to specify which `MyInt` you want. The closest syntax would be `V[0][3]=10;`, to edit the `MyInt` at the 0th index. Not an answer, because I suspect you've written the wrong question. – Mooing Duck Oct 14 '22 at 15:56
  • How did you come to the conclusion that this is what you need? To me this looks like an [XY problem](https://xyproblem.info/). – Ted Lyngmo Oct 14 '22 at 17:26

3 Answers3

2

Note: This answer was written when OPs question was:

I would like to have it like:

MyInt V = new MyInt[10];
V[3]=10;

I'll leave this answer up in case anyone is interested in a solution for that.

#include <cstddef>

class MyInt {
public:
    MyInt() = default;
    MyInt(MyInt* d) : data(d) {} // constructor taking a `MyInt*`
    // ... rule of 5 implementation needed here ...

    MyInt& operator[](size_t idx) { return data[idx]; }
    MyInt& operator=(int) { return *this; }

private:
    MyInt* data = nullptr;
};

int main() {
    MyInt V = new MyInt[10];
    V[3]=10;
}

Note that there's no way for V to know how many elements data is pointing at.

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
1

Following the link to your earlier question, and the requirements you've added there, V[3] is undefined behaviour.

You have changed the meaning of new [] to return a pointer to a single object.

You need to completely rethink your design, such that there are 10 MyInt objects for V to point to.

struct MyCounts
{
    int num_read = 0;
    int num_write = 0;
};

class MyInt
{
    int value;
    MyCounts * counts;

    static void* operator new[](size_t n){
        void * ptr = malloc(sizeof(MyCounts) + n * sizeof(MyInt));
        MyCounts * counts = new (ptr) MyCounts;
        ptr = static_cast<void *>(counts + 1);
        for (size_t i = 0; i < n; ++i, ptr += sizeof(MyInt)) {
            new (ptr) MyInt{ counts };
        }
        return static_cast<void *>(counts + 1);
    }

    static void* operator delete[](void* ptr, size_t n){
        for (MyInt * last = reinterpret_cast<MyInt *>(ptr) + n; --last != ptr; ) {
            last->~MyInt();
        }
        ptr -= sizeof(MyCounts);
        reinterpret_cast<MyCounts *>(ptr)->~MyCounts();
        free(ptr);
    }
public:
    MyInt& operator=(int i) { value = i; ++counts->num_write; return *this; }
    operator int() const { ++counts->num_read; return value; }
};
Caleth
  • 52,200
  • 2
  • 44
  • 75
  • I **lol**ed so this must be worth an upvote. I hope this is what OP wants so that discussing the XY elephant in the room becomes the next obvious step. – Ted Lyngmo Oct 14 '22 at 16:17
  • 1
    @TedLyngmo yeah, this really shouldn't be what they end up with – Caleth Oct 14 '22 at 16:19
0

I would like to have it like:

MyInt* V = new MyInt[10];
V[3]=10;

You need MyInt to implement an operator= taking an int to "write" to it, and a conversion oeprator to "read" from it:

#include <iostream>

struct MyInt
{
    int value;
    MyInt& operator=(int v) { value = v; return *this; }
    operator int() const { return value; };
};


int main()
{
    MyInt *V = new MyInt[10];
    V[3]=10;
    std::cout << V[3] << '\n';
}
YSC
  • 38,212
  • 9
  • 96
  • 149