views:

376

answers:

2

I'm trying to do some refactoring of code, and have run into a problem. The program has a data manager that returns pointers to arrays of structures as a void*. One of the new types of data, instead of having a single pointer to an array of structures, has two pointers to arrays of numbers. The problem is that all the processing code is done by accessing array[index].qwTimestamp and array[index].snSample which is common to all record types.

I thought that doing an override of the array access operator( [] ) like the following might solve the problem:

class ADRec {

public:
    ADRec(unsigned __int64* ts, __int32* data, unsigned index = 0): mTimestamps(ts), mDataPoints(data), mIndex(index) {

     qwTimeStamp = mTimestamps[mIndex];
     snSample = mDataPoints[mIndex];

    }
    ADRec operator[](unsigned i) {
     return ADRec(mTimestamps, mDataPoints, i);

    }
    unsigned __int64 qwTimeStamp;
    __int32 snSample;

private:
    unsigned __int64* mTimestamps;
    __int32* mDataPoints;
    unsigned mIndex;
};

This approach works fine if you are using an object:

unsigned __int64 ts[] = { 2, 3, 4, 5};
__int32 data[] = {4, 6, 8, 10};

ADRec tmp =  ADRec(ts, data, 0);

ASSERT(tmp[0].qwTimeStamp == 2);
ASSERT(tmp[0].snSample == 4);
ASSERT(tmp[1].qwTimeStamp == 3);
ASSERT(tmp[1].snSample == 6);

But fails if you use a pointer to an object:

unsigned __int64 ts[] = { 2, 3, 4, 5};
__int32 data[] = {4, 6, 8, 10};

ADRec* tmp =  new ADRec(ts, data, 0);

ASSERT(tmp[0].qwTimeStamp == 2);
ASSERT(tmp[0].snSample == 4);
ASSERT(tmp[1].qwTimeStamp == 3); //fails
ASSERT(tmp[1].snSample == 6); //fails

C++ is indexing off of the pointer when tmp[1] is called, and thus pointing to random memory.

Is it possible to override the way C++ indexes off of a pointer to an object, or some other mechanism that would accomplish the same goal?

+8  A: 

No, it isn't possible - pointers are considered to be of a built-in type and so cannot have their operators overloaded. However, you can certainly create smart pointer classes (classes that act like pointers, but with added abilities) and overload their operators - take a look at your compiler's implementation of std::auto_ptr, for example.

anon
I agree with this, make your own "pointer" class and overload the array access on that. Also you can overload the "address-of" operator on your original class to return your custom pointer.
Sumudu Fernando
A: 

Try dereferencing the pointer first:

ADRec* tmp =  new ADRec(ts, data, 0);

ASSERT(tmp[0][1].qwTimeStamp == 3);
// or
ASSERT((*tmp)[1].qwTimeStamp == 3);
Darryl
Unfortunately, that won't work since all other processing functions expect a real array of records. I'd have to put in a special case for this object, which is what I'm trying to avoid.
bsruth