Which design in better?

N

Nitesh

Objects of type X are basic building blocks of my application and
there are a few functions which return XHandle (typedef X** XHandle).
The task at hand needs to use a couple of these functions and then
iterate over X objects.
Because its done frequently and it separates iteration from task-at-
hand'logic we decided to create iterator.

Assuming the availability of functions GetXHandleSize(XHandle) and
DisposeXHandle(XHandle) there are two alternatives.

<b>Option1:</b> Using simple inheritance
class XHandleIterator {
public:
XHandleIterator(void) : mHandle(0L), mCount(0) {}
~XHandleIterator() { if (mHandle != 0L) DisposeXHandle(mHandle); }

bool Done(void) { return mCount > 0; }
// Pre-increment operator
XHandleIterator& operator++(void) { --mCount; return *this; } // Am
iterating over backwards
// Post-increment operator..
// De-referencing operator
X& operator *(void) { return (*mHandle)[mCount-1]; }
protected:
XHandle mHandle;
int mCount;
};

class XHandleIteratorOne : public XHandleIterator {
public:
XHandleIteratorOne(SomeType obj) {
// Creates XHandle someway. Assigns to mHandle and mCount
}
};

class XHandleIteratorTwo : public XHandleIterator {
XHandleIteratorTwo(SomeType obj) {
// Creates XHandle in another way. Assigns to mHandle and mCount
}
};

<b>Option2:</b> Policy based design
template<typename HandleCreator>
class XHandleIterator {
public:
XHandleIterator (SomeType obj) : mHandle(0L), mCount(0)
{
HandleCreator::Create(obj, &mHandle);
mCount = GetXHandleSize(mHandle)/sizeof(X);
}
~XHandleIterator() { if (mHandle != 0L) DisposeXHandle(mHandle); }
bool Done(void) { return mCount > 0; }
// Pre-increment operator
XHandleIterator& operator++(void) { --mCount; return *this; }
// Post-increment operator...
// De-referencing operator
X& operator *(void) { return (*mHandle)[mCount-1]; }
private:
XHandle mHandle;
int mCount;
};

struct XHandleCreator1 {
static void Create(SomeType obj, XHandle *handle) {
// Creates XHandle someway. Assigns to handle
}
};

struct XHandleCreator2 {
static void Create(SomeType obj, XHandle *handle) {
// Creates XHandle in another way. Assigns to handle
}
};

typedef XHandleIterator<XHandleCreator1> XHandleIteratorOne;
typedef XHandleIterator<XHandleCreator2> XHandleIteratorTwo;

I am confused over which is the right way to do in this case with all
stipulations stated at the top. The main thing I like about 2nd one is
that mHandle and mCount are private.
Please comment on which of the above alternative is better?

Thanks
Nitesh
 
N

Nitesh

A pointer to a pointer?


Can you explain, precisely, why you've decided to reinvent the wheel, why
none of the STL containers and iterators do not meet your needs, and what
does your handmade iterator class does that none of the STL iterators do.

std::vector, std::list, std::set, std::map, and a few other STL containers,
all give you perfectly usable iterator objects. Any particular reasons why
none of them meet your needs?



Both of your options are difficult to follow. Pick an STL container that
meets your needs, and use the iterator definition that it gives you.

 application_pgp-signature_part
< 1KViewDownload

Its a legacy app. And I am making use of existing functions which
return me Handle to objects of type X. i.e. I have a pointer to an
array pointer and indexing that array is enough to obtain an array
element, So this option was chosen instead of first creating an STL
container from the handle.

Do you still suggest to first copy the handle elements to an STL
container (copy is not constly because its just pointer to X) and then
use STL iterators.

The iterator was made simple just to focus on the problem of confusion
over choosing between alternate approaches. i.e. You have to write
your own iterator. So the problem can be restated as:
You have to write the iterator, but the collection over which it
iterates is obtained in different ways. In that case whats the better
way? Using simple inheritance and letting derived classes obtain the
collection OR using HandleCreation policy? Or any other way?

Thanks
Nitesh
 
N

Nitesh

Nitesh <[email protected]> kirjutas:


Objects of type X are basic building blocks of my application and
there are a few functions which return XHandle (typedef X** XHandle).
The task at hand needs to use a couple of these functions and then
iterate over X objects.
Because its done frequently and it separates iteration from task-at-
hand'logic we decided to create iterator.
Assuming the availability of functions GetXHandleSize(XHandle) and
DisposeXHandle(XHandle) there are two alternatives.
<b>Option1:</b> Using simple inheritance
class XHandleIterator {
public:
 XHandleIterator(void) : mHandle(0L), mCount(0) {}
 ~XHandleIterator() { if (mHandle != 0L) DisposeXHandle(mHandle); }
 bool Done(void) { return mCount > 0; }
 // Pre-increment operator
 XHandleIterator& operator++(void) { --mCount; return *this; } // Am
iterating over backwards
 // Post-increment operator..
 // De-referencing operator
 X& operator *(void) { return (*mHandle)[mCount-1]; }
protected:
 XHandle mHandle;
 int mCount;
};
class XHandleIteratorOne : public XHandleIterator {
public:
 XHandleIteratorOne(SomeType obj) {
 // Creates XHandle someway. Assigns to mHandle and mCount
}
};
class XHandleIteratorTwo : public XHandleIterator {
 XHandleIteratorTwo(SomeType obj) {
 // Creates XHandle in another way. Assigns to mHandle and mCount
 }
};
<b>Option2:</b> Policy based design
template<typename HandleCreator>
class XHandleIterator {
public:
 XHandleIterator (SomeType obj) : mHandle(0L), mCount(0)
 {
  HandleCreator::Create(obj, &mHandle);
  mCount = GetXHandleSize(mHandle)/sizeof(X);
 }
 ~XHandleIterator() { if (mHandle != 0L) DisposeXHandle(mHandle); }
 bool Done(void) { return mCount > 0; }
  // Pre-increment operator
 XHandleIterator& operator++(void) { --mCount; return *this; }
 // Post-increment operator...
 // De-referencing operator
 X& operator *(void) { return (*mHandle)[mCount-1]; }
private:
 XHandle mHandle;
 int mCount;
};
struct XHandleCreator1 {
     static void Create(SomeType obj, XHandle *handle) {
         // Creates XHandle someway. Assigns to handle
     }
};
struct XHandleCreator2 {
     static void Create(SomeType obj, XHandle *handle) {
         // Creates XHandle in another way. Assigns to handle
     }
};
typedef XHandleIterator<XHandleCreator1> XHandleIteratorOne;
typedef XHandleIterator<XHandleCreator2> XHandleIteratorTwo;
I am confused over which is the right way to do in this case with all
stipulations stated at the top. The main thing I like about 2nd one is
that mHandle and mCount are private.
Please comment on which of the above alternative is better?
Thanks
Nitesh

It appears you want the iterator to perform two tasks: iterate over the
array, and dispose the array when done. It would be cleaner to keep these
tasks separate IMO. To follow the STL pattern there should be a
"container" class, from where the iterators can be obtained by begin()
and end() member functions. The fact that the data is actually living
elsewhere does not have any significance. The "container" object will
call Dispose in its destructor.

The usage would go like this:

XContainer my_xvector = ObtainXHandleInWhatEverWay();

for(XContainer::iterator p = my_xvector.begin();
        p != my_xvector.end(); ++p) {

        X& xref = *p;
        // Do whatever with X

}

I see no need for inheritance or policy-based templates here, based on
the info you provided. The container object should just have a
constructor and/or an assignment operator taking XHandle as a parameter,
regardless of in which way the handle was obtained. Mixing up this class
with different ways to obtain the handle would just convolute the design.
If really needed, one could provide a separate "factory" class for taking
care of obtaining the handle in different ways.

hth
Paavo

This is thing I need to do
1) Obtain handle
2) Iterate over the handle
3) Dispose the obtained handle

For my task its the 1st (obtaining handle) that differs. 2nd and 3rd
(iterating over and disposing) are always done in same way so I put
them in same class.

But with your explanation it seems reasonable not to mix 2nd and 3rd.
So, obtaining and disposing handle should be responsibility of one
class and iterating over that should be done by another but related
class.

How about having one XContainer base class that has a nested public
Iterator class that knows how to iterate over the XContainer? And
there will be derived classes OR template specializations
XContainerOne/Two that know how to obtain the handle. Again which of
these two is better?

Thanks
Nitesh
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top