0

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?

Jon Seigel
  • 12,251
  • 8
  • 58
  • 92
bsruth
  • 5,372
  • 6
  • 35
  • 44
  • 2
    Any identifier starting with a double underscore is reserved by the standard. Don't use '__int32' etc. See http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier/228797#228797 – Martin York Aug 27 '09 at 16:23
  • This program will be used in a VS2008, Windows only environment, so it isn't conforming strictly to the standard. But it is a good thing to know for the future. – bsruth Aug 27 '09 at 17:14
  • 1
    @Martin Reserved by the standard FOR THE IMPLEMENTATION. __int32 et al are part of the MS implementation and so perfectly OK to be used, so long as portability is not an issue. –  Aug 27 '09 at 17:40
  • @bsruth If you are building for Windows, use MinGW and do not __int64 but long long. GCC is better in following the standard – user877329 Mar 28 '12 at 18:27

2 Answers2

9

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.

  • 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 Aug 27 '09 at 16:52
0

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
  • 5,907
  • 1
  • 25
  • 36
  • 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 Aug 27 '09 at 16:33