What is better std::list or CList?

Hi All,

What do you think is better to use std::list or CList. I am trying to handle the object of a Tree control. But I want to be able either to insert in the midlle and sort items easy. :confused: :confused:

What are the advantages of using one or the other.??

Thank you in advance...
[315 byte] By [ayana] at [2007-11-18 3:13:18]
# 1 Re: What is better std::list or CList?
the std::list is standard c++.
CList is MFC specific. (Microsoft specific, thus Windows specific).

If you want to have portable code (on other plateforms such as Linux), avoid CList at all cost.

If not. Go with your needs. In my opinion, all you ever need is a std::list.
proxima centaur at 2007-11-8 1:19:20 >
# 2 Re: What is better std::list or CList?
std::list is superior for many reasons.

a) It's standard C++.

b) It's not MFC specific. CList can only be used in MFC applications. The std::list can be used in any application -- MFC, non-MFC, console, Windows, Unix, etc. Why? see item a)

c) It is more powerful than CList.

However, I don't understand what a GUI component (the Tree Control) has to do with using std::list over CList. Maybe you should explain this in more detail.

Regards,

Paul McKenzie
Paul McKenzie at 2007-11-8 1:20:21 >
# 3 Re: What is better std::list or CList?
Also std::list has a sort() member function. I don't
think the CList does.
Philip Nicoletti at 2007-11-8 1:21:14 >
# 4 Re: What is better std::list or CList?
Sorry, I didn't mention it. My program is actually an MFC Dlg application. And I start handling my objets in a std::list. But I feel like I have had to write a lot of code to do something. Sometimes I think it would be better to switch to CList.

Thanks for your quick response.:D :D :D
ayana at 2007-11-8 1:22:16 >
# 5 Re: What is better std::list or CList?
Originally posted by ayana
Sorry, I didn't mention it. My program is actually an MFC Dlg application. And I start handling my objets in a std::list. But I feel like I have had to write a lot of code to do something. Sometimes I think it would be better to switch to CList.

Thanks for your quick response.:D :D :D What is the extra code you have to write? You mentioned you have to sort the list. For a std::list, there is the sort() function. Where is the sort function for CList? There isn't any. So far, std::list saved you from writing a sort function.

Maybe you should give an example of what you had to write when using std::list that you didn't have to write when you use CList.

Regards,

Paul McKenzie
Paul McKenzie at 2007-11-8 1:23:16 >
# 6 Re: What is better std::list or CList?
Originally posted by Philip Nicoletti
Also std::list has a sort() member function. I don't
think the CList does.

Are you sure that sort() is a member of std::list?
Gabriel Fleseriu at 2007-11-8 1:24:23 >
# 7 Re: What is better std::list or CList?
Sure is! Although std::sort will be just as correct, list::sort could possibly be faster.

Jeff
jfaust at 2007-11-8 1:25:24 >
# 8 Re: What is better std::list or CList?
Yes, sort() is part of std::list and I know CList does not have a sort function but it does have the option to insert items in the position I want, this will supply my need of using sort().

I am using three clases Item->SubMenu->Menu. Each type of object is contain by its sucessor in a list. Lets say Menu contains a list of SubMenus, an this one a list of items. There is also a Main Menu List.

I overwrite the sort funtion in Item since it is the basic class this is the code. I personalize my search based on an specific value contained in the object.

bool operator<(const CItem &item2) const {return iPosition < item2.iPosition;}

Then I have my CTreeCtrl implemented class where I called sort, but it looks like it never get called. Inside my Drag and Drop code I insert the new item dropped based on the parent type to be insert on.

if(pMainMenu == NULL)
cMenus->push_front( (CMainMenu*)pItem );
else if(pMainMenu->IsKindOf(RUNTIME_CLASS(CMainMenu)))
pMainMenu->MainMenuList->push_front((CSubMenu*)pItem);
else if(pMainMenu->IsKindOf(RUNTIME_CLASS(CSubMenu)))
pMainMenu->ItemsList->push_front(pItem);

After the insertion I called sort based on my object values. MainMenuList and ItemsList are the lists part of the object that contain SubMenus and Items respectivelly.

if(pMainMenu->IsKindOf(RUNTIME_CLASS(CMainMenu)))
pMainMenu->MainMenuList->sort();
else if(pMainMenu->IsKindOf(RUNTIME_CLASS(CSubMenu)))
pMainMenu->ItemsList->sort();

It never sorts my items... Am I doing really crazy things?. Thank you for your help again.
ayana at 2007-11-8 1:26:20 >
# 9 Re: What is better std::list or CList?
Use STL whenever possible.

Kuphryn
kuphryn at 2007-11-8 1:27:19 >
# 10 Re: What is better std::list or CList?
pMainMenu->ItemsList->sort();

This is your culprit. Since your list is a list of pointers, it is merely sorting the pointers.

You can use a predicate to fix this, as follows:

template<typename T>
struct deref_greater : public std::greater<T>
{
bool operator()(T l, T r)
{
return *l > *r;
}
};

...
pMainMenu->ItemsList->sort(deref_greater<CItem*>());

Edit: Added '()' for deref_greater construction.

Jeff
jfaust at 2007-11-8 1:28:31 >
# 11 Re: What is better std::list or CList?
I just found out why list has a sort. std::sort requires a random access iterator, which list does not have.

You would probably be better off using std::vector instead of std::list. Sorting as well as most other things will be faster.

Rule of thumb: default to vector as your container of choice and if it doesn't quite fit what you need, then look to the other containers.

Jeff
jfaust at 2007-11-8 1:29:26 >
# 12 Re: What is better std::list or CList?
Originally posted by ayana
Yes, sort() is part of std::list and I know CList does not have a sort function but it does have the option to insert items in the position I want, this will supply my need of using sort().
So does std::list. The std::list::insert() function is available. You need to use advance to get to the position where you want to insert. What is usually done is to get an iterator to the first item, and advance to where you want to insert the item

#include <list>
#include <algorithm>
std::list<int> IList;
//...
// Insert a 17 after position 2
std::list<int>::iterator it = IList.begin();
std::advance(it, 2);
IList.insert(it, 178);

I personalize my search based on an specific value contained in the object.
OK so far.
bool operator<(const CItem &item2) const {return iPosition < item2.iPosition;}

if(pMainMenu == NULL)
cMenus->push_front( (CMainMenu*)pItem );
else if(pMainMenu->IsKindOf(RUNTIME_CLASS(CMainMenu)))
pMainMenu->MainMenuList->push_front((CSubMenu*)pItem);
else if(pMainMenu->IsKindOf(RUNTIME_CLASS(CSubMenu)))
pMainMenu->ItemsList->push_front(pItem);
Your operator < is not being called. You need to use the predicate version of the sort function.

This code should work:

template <>
struct std::greater<CItem*>
{
bool operator()(const CItem* lhs, const CItem* rhs) const
{
return lhs->iPosition < rhs->iPosition;
}
};

//...

pMainMenu->ItemsList->sort(std::greater<CItem*>());

The reason for the std::greater<> is that the VC++ version of std::list is broken, plain and simple. If it were not broken, all you would need is to specify a functor or function pointer for the predicate function. Hopefully this gets around the problem.

Here is a small sample program that maybe easier to understand:

#include <list>
#include <iostream>

struct foo
{
int nValue;
foo(int n=0) : nValue(n){ }
};

typedef std::list<foo *> pFooList;

template <>
struct std::greater<foo*>
{
bool operator()(const foo* lhs, const foo* rhs) const
{
return lhs->nValue < rhs->nValue;
}
};

using namespace std;

int main()
{
pFooList FL;
pFooList::iterator it;

FL.push_back(new foo(1));
FL.push_back(new foo(3));
FL.push_back(new foo(2));

it = FL.begin();
while ( it != FL.end())
{
cout << (*it)->nValue << endl;
++it;
}
cout << endl;
FL.sort(std::greater<foo*>());
it = FL.begin();
while ( it != FL.end())
{
cout << (*it)->nValue << endl;
++it;
}
cout << endl;

}

Forget about the memory leak in the sample above. I only posted this to illustrate how list::sort would work for something similar to what you are doing.

Regards,

Paul McKenzie
Paul McKenzie at 2007-11-8 1:30:24 >
# 13 Re: What is better std::list or CList?
I can't remember exactly how you iterate through a CList (haven't used one in ages), but I suspect it follows that peculiar Microsoftian technique involving a POSITION and calling something like GetNextPosition which not only returns the next, but alters one of its arguments, so that you're never quite sure when you've hit the end........

STL iterators are much simpler.

I recently had to work with Tree and List Controls. I found it easier to do everything with a custom tree class (as near STL-container-compatible as I could get it) and a std::list, all wrapped up in some handler classes. All I allowed the controls to do was to notify me of events. I kept all of my info outside of them and used STL algorithms to locate it. Updates were done by storing handles (HTREEITEM and HLISTITEM) in my exterior data, for easy access to the actual items. I found this much simpler and easier to work with than trying to locate the data by retrieving it from the control with GetFirstPosition() and all that garbage. By making my tree "container" STL-compatible (with iterators), I was able to use std::find in all its glory. Have you tried to use the "find" facilities of CTreeCtrl?
Graham at 2007-11-8 1:31:32 >
# 14 Re: What is better std::list or CList?
Thank you Paul McKenzie. I will try this which is very understandable for me....:D

Graham,
No, I have not use "find" in the TreeCtrl, is anything that can help me from there?
ayana at 2007-11-8 1:32:28 >
# 15 Re: What is better std::list or CList?
Thank you very much, Paul McKenzie. I was able to solve my sort problem just using the code to insert in the position I want. That help me to reduce my code also. I haven't try to implement the sort code you also attached to your response, but I will. I want to see how it works.

Thank you again...:D
ayana at 2007-11-8 1:33:36 >
# 16 Re: What is better std::list or CList?
This example provieded by Paul McKenzie works fine with VC but fails in a Sun compiler:

Error: Could not find a match for std::list<foo*, std::allocator<foo*>>::sort(std::greater<foo *>).

Does someone has any hints?

Thanks,
Herminio
hpinto at 2007-11-8 1:34:31 >
# 17 Re: What is better std::list or CList?
This example provieded by Paul McKenzie works fine with VC but fails in a Sun compiler:That is because it is only supposed to be the workaround for the Visual C++ bug.

For Sun, all you need to do is call sort with the predicate function. You do not need to use std::greater. Please read my post carefully:

The reason for the std::greater<> is that the VC++ version of std::list is broken, plain and simple. If it were not broken, all you would need is to specify a functor or function pointer for the predicate function.

#include <list>
#include <iostream>

struct foo
{
int nValue;
foo(int n=0) : nValue(n){ }
};

typedef std::list<foo *> pFooList;

bool IsGreaterPointer(const foo* lhs, const foo* rhs)
{
return lhs->nValue < rhs->nValue;
}

using namespace std;

int main()
{
pFooList FL;
pFooList::iterator it;

FL.push_back(new foo(1));
FL.push_back(new foo(3));
FL.push_back(new foo(2));

it = FL.begin();
while ( it != FL.end())
{
cout << (*it)->nValue << endl;
++it;
}
cout << endl;
FL.sort(IsGreaterPointer);
it = FL.begin();
while ( it != FL.end())
{
cout << (*it)->nValue << endl;
++it;
}
cout << endl;
}

Regards,

Paul McKenzie
Paul McKenzie at 2007-11-8 1:35:30 >
# 18 Re: What is better std::list or CList?
Thanks a lot.

Herminio
hpinto at 2007-11-8 1:36:36 >
# 19 Re: What is better std::list or CList?
I just found out why list has a sort. std::sort requires a random access iterator, which list does not have.

You would probably be better off using std::vector instead of std::list. Sorting as well as most other things will be faster.

Rule of thumb: default to vector as your container of choice and if it doesn't quite fit what you need, then look to the other containers.

True but since std::list is implemented as a linked list and std::vector as an array, inserting items into the middle of the list is much faster for std::list than std::vector, because std::list just has to manipulate some previous and next pointers in the nodes, while std::vector might have to recopy the entire array to insert an item. Since the OP is doing a lot of ionsert operations, I would recommend to stick with std::list.
HighCommander4 at 2007-11-8 1:37:39 >
# 20 Re: What is better std::list or CList?
I just found out why list has a sort. std::sort requires a random access iterator, which list does not have.

You would probably be better off using std::vector instead of std::list. Sorting as well as most other things will be faster.

Rule of thumb: default to vector as your container of choice and if it doesn't quite fit what you need, then look to the other containers.

JeffHi All,

Some comments:
1. As far as I know, std::vector does not have a sort method.

2. The reason because foo wasn't working in the Sun Studio is because you have to use another library: -library=stlport4

Thanks for your help and comments.

Herminio
hpinto at 2007-11-8 1:38:38 >
# 21 Re: What is better std::list or CList?
1. As far as I know, std::vector does not have a sort method.

Yes, however, it is a random access container meaning you can use std::sort to sort the vector, which is even more efficient. However, for reasons mentioned in my previous post, I still think you should use std::list.
HighCommander4 at 2007-11-8 1:39:38 >
# 22 Re: What is better std::list or CList?
Not sure what you mean by std::sort() being even more efficient. list::sort() has the advantage that it doesn't require the contents of the list to be copied - the whole sort can be done by reassigning pointers, so it's not obvious that one will be more efficient than the other. Anyway, you should pick the container you use based on your needs, not on "default" positions or perceived efficiency in a single area.
Graham at 2007-11-8 1:40:40 >
# 23 Re: What is better std::list or CList?
Not sure what you mean by std::sort() being even more efficient. list::sort() has the advantage that it doesn't require the contents of the list to be copied - the whole sort can be done by reassigning pointers, so it's not obvious that one will be more efficient than the other.

True. At the end of the day, list::sort() can indeed be considerably faster (especially if the objects held in the container are large). What I meant is that list::sort() has to use a different sorting algorithm than std::sort() (since list::sort() cannot use random access iterators) and that algorithm might be slower in terms of complexity. However, as you said, as no copying is required in list::sort(), it can in many cases be faster.
HighCommander4 at 2007-11-8 1:41:41 >
# 24 Re: What is better std::list or CList?
That is because it is only supposed to be the workaround for the Visual C++ bug.

Hi Paul,

Is it okay to specify a predicate-function pointer in a VC-based STL implementation, or am I bound to public std::greater <MyClass> which to my personal tastes looks ugly!

Thanks,
Sid
Siddhartha at 2007-11-8 1:42:45 >