STL list in a wrapper class

  • Thread starter Christian Christmann
  • Start date
C

Christian Christmann

Hi,

I need an STL list and was thinking of putting
the list in wrapper class.

The reason for my decision is that you can
much better perform consistency checks.
For instance, I need a function to append a
list to another. Using a wrapper class I could
do something like:
void List<ELEMENT>::Append(List<ELEMENT>* L)
{
if (!L) return;
mylist->splice(mylist->end(), *(L->GetList()));
}

Using the function splice directly without a wrapper
class wouldn't perform a check on !L and could
possibly transform the old list (mylist) in an inconsistent
state.


Another benefit of using a wrapper class is that you can
encapsulate functions which need more that one
statement. As example consider a function to return the next
element in a list:
ELEMENT* List<ELEMENT>::NextElement(ELEMENT* x)
{
if (mylist->empty()) return NULL;

typename list<ELEMENT*>::iterator it = find(mylist->begin(),
mylist->end(), x);
if (it != mylist->end())
return *(++(it));
else
return NULL;
}

No functions but just a direct use of the statements in the source code
would on the one hand produce unnecessarily more code and on the
other hand make the code worse readable.


Do you agree to my considerations or are you of the opinion that
a wrapper class for STL lists is an overkill.

Thank you for your comments.

Chris
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

Christian said:
Do you agree to my considerations or are you of the opinion that
a wrapper class for STL lists is an overkill.

In a situation like that I prefer another point of view: I need my type of
list, not a standard list. I made a list class, or a template class for
lists, and I can use the standard list inside but that is an implementation
detail, not a wrapping.
 
L

Larry I Smith

Christian said:
Hi,

I need an STL list and was thinking of putting
the list in wrapper class.

The reason for my decision is that you can
much better perform consistency checks.
For instance, I need a function to append a
list to another. Using a wrapper class I could
do something like:
void List<ELEMENT>::Append(List<ELEMENT>* L)

Pass the List by ref and this problem goes away:
void List<ELEMENT>::Append(List<ELEMENT> & L)
{
myList->splice(myList->end(), L.GetList());
}
{
if (!L) return;
mylist->splice(mylist->end(), *(L->GetList()));
}

Using the function splice directly without a wrapper
class wouldn't perform a check on !L and could
possibly transform the old list (mylist) in an inconsistent
state.


Another benefit of using a wrapper class is that you can
encapsulate functions which need more that one
statement. As example consider a function to return the next
element in a list:
ELEMENT* List<ELEMENT>::NextElement(ELEMENT* x)
{
if (mylist->empty()) return NULL;

typename list<ELEMENT*>::iterator it = find(mylist->begin(),
mylist->end(), x);
if (it != mylist->end())
return *(++(it));
else
return NULL;
}

Why all of the gyrations? The above function is way more complex
(and slow) because of the design decision to use 'ELEMENT *'
rather than 'std::list' iterators. If you have an iterator to
a list element, just increment the iterator to get the next
element. Your code forces a linear search of the list just to
find/increment to the 'next' element.
No functions but just a direct use of the statements in the source code
would on the one hand produce unnecessarily more code and on the
other hand make the code worse readable.


Do you agree to my considerations or are you of the opinion that
a wrapper class for STL lists is an overkill.

Thank you for your comments.

Chris

This is overkill, complex, and slows things down.
just use std::list, std::list iterators, etc the way
they are intended.

Regards,
Larry
 
A

Andre Kostur


Hopefully some useful critique:
I need an STL list and was thinking of putting
the list in wrapper class.

The reason for my decision is that you can
much better perform consistency checks.
For instance, I need a function to append a
list to another. Using a wrapper class I could
do something like:
void List<ELEMENT>::Append(List<ELEMENT>* L)
{
if (!L) return;
mylist->splice(mylist->end(), *(L->GetList()));
}

Why does this take it's parameter by pointer, why not by reference? Then
you don't have to worry about NULL pointers.
Using the function splice directly without a wrapper
class wouldn't perform a check on !L and could
possibly transform the old list (mylist) in an inconsistent
state.

If you're using references, then NULL isn't an issue...
Another benefit of using a wrapper class is that you can
encapsulate functions which need more that one
statement. As example consider a function to return the next
element in a list:
ELEMENT* List<ELEMENT>::NextElement(ELEMENT* x)
{
if (mylist->empty()) return NULL;

typename list<ELEMENT*>::iterator it = find(mylist->begin(),
mylist->end(), x);
if (it != mylist->end())
return *(++(it));

Undefined behaviour. If the "current" element is the last element in the
list, you'll increment the iterator (so now it's .end() ), and then
dereference it. You can't dereference an .end() iterator.
else
return NULL;
}

On a side note, are you sure you want to store pointers to ELEMENT in
your list? This would mean that when you try to call your NextElement
method, you're going to need to pass in the same pointer value that you
had earlier inserted into the list.
No functions but just a direct use of the statements in the source code
would on the one hand produce unnecessarily more code and on the
other hand make the code worse readable.

Any particular reason everything seems to be "naked" pointer-based?
 
K

Kai-Uwe Bux

Christian said:
I need an STL list and was thinking of putting
the list in wrapper class.

The reason for my decision is that you can
much better perform consistency checks.
For instance, I need a function to append a
list to another. Using a wrapper class I could
do something like:
void List<ELEMENT>::Append(List<ELEMENT>* L)
{
if (!L) return;
mylist->splice(mylist->end(), *(L->GetList()));
}

Using the function splice directly without a wrapper
class wouldn't perform a check on !L and could
possibly transform the old list (mylist) in an inconsistent
state.

The need for consistency check arises from the use of pointers.
What about references:

template < typename T >
void concat ( std::list< T > & front, std::list< T > & tail ) {
front.splice( front.end(), tail );
}

Another benefit of using a wrapper class is that you can
encapsulate functions which need more that one
statement. As example consider a function to return the next
element in a list:
ELEMENT* List<ELEMENT>::NextElement(ELEMENT* x)
{
if (mylist->empty()) return NULL;

typename list<ELEMENT*>::iterator it = find(mylist->begin(),
mylist->end(), x);
if (it != mylist->end())
return *(++(it));
else
return NULL;
}

No functions but just a direct use of the statements in the source code
would on the one hand produce unnecessarily more code and on the
other hand make the code worse readable.

Again, I find the use of pointers in this context highly questionable. As a
conesequence, this routine returns 0 in many cases:

empty list,
x not found,
x is last element, and
the element following x just happens to be 0
(after all, this is list<ELEMENT*>)

The burden of checking which condition has occured rests with the caller.
Thus, as a function in a library, NextElement is poorly designed; although
it might fit the bill perfectly for the application you have in mind.



Best

Kai-Uwe Bux
 

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,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top