STL Algorithms
-
I continuously see people asking questions about code they have written that involves loops for things such as pulling in input, displaying output, transforming data in a collection, etc. All of which can be done using STL algorithms using much less code, but instead is done using (usually) complex code written by the programmer asking the question. Why is it that so many people don't use the STL algorithms?
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac
-
I continuously see people asking questions about code they have written that involves loops for things such as pulling in input, displaying output, transforming data in a collection, etc. All of which can be done using STL algorithms using much less code, but instead is done using (usually) complex code written by the programmer asking the question. Why is it that so many people don't use the STL algorithms?
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac
I'd say because they don't know they are there, or don't know how to use them. Which is why I am often a voice in the wilderness when people ask MFC container questions - because the day will come that they wish their CArray was a vector, so they could just call random_shuffle.
Christian Graus - Microsoft MVP - C++ Metal Musings - Rex and my new metal blog
-
I'd say because they don't know they are there, or don't know how to use them. Which is why I am often a voice in the wilderness when people ask MFC container questions - because the day will come that they wish their CArray was a vector, so they could just call random_shuffle.
Christian Graus - Microsoft MVP - C++ Metal Musings - Rex and my new metal blog
Hmmmm - given that STL algorithms are parameterised on iterator type, you probably can use them on a CArray by exploiting raw pointers to the data...like this, possibly?
CArray<int> blah; // Populate it std::random_shuffle(blah.GetData(), blah.GetData() + blah.GetSize());
Not that that's a good reason for using MFC containers - I don't think there is one, is there?
-
I'd say because they don't know they are there, or don't know how to use them. Which is why I am often a voice in the wilderness when people ask MFC container questions - because the day will come that they wish their CArray was a vector, so they could just call random_shuffle.
Christian Graus - Microsoft MVP - C++ Metal Musings - Rex and my new metal blog
See, that amazes me. Mostly because so many of these questions are largely homework related. I know when I was in college working for my CS degree, we were actually marked off if we didn't use the STL algorithms for certain required classes. And this was less than a couple years after the standard was finalized. The nice thing about many of the STL algorithms is their flexibility. You can still use CArray in most of them without too many problems (albeit, it doesn't look quite as pretty as using a STL container).
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac
-
I continuously see people asking questions about code they have written that involves loops for things such as pulling in input, displaying output, transforming data in a collection, etc. All of which can be done using STL algorithms using much less code, but instead is done using (usually) complex code written by the programmer asking the question. Why is it that so many people don't use the STL algorithms?
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac
I can tell you why I don't use the algorithms too much * The VC 6 STL docs blow so I haven't read them much and don't know what algorithm functions exist * The STL naming scheme sucks so it's hard to figure out what some functions are for from just their name (and the docs aren't much help, see 1. I mean, seriously, WTF does "
bind2nd
" do??) * Most of the time when I do use algorithms, it involves writing a special-case functor for just that usage, which is workable but just feels sloppy. I know aboutmem_fun_ref
and the like, but I haven't taken the time to figure out how they work. * Instead of fighting with the docs, I'll just write a for loop and be done with it--Mike-- Visual C++ MVP :cool: LINKS~! Ericahist | PimpFish | CP SearchBar v3.0 | C++ Forum FAQ
-
I continuously see people asking questions about code they have written that involves loops for things such as pulling in input, displaying output, transforming data in a collection, etc. All of which can be done using STL algorithms using much less code, but instead is done using (usually) complex code written by the programmer asking the question. Why is it that so many people don't use the STL algorithms?
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac
This makes much more sense to me (but I'm old school): vector vec; for (int i = 0; i < vec.size(); i++) { } than vector vec; vector::iterator it; for (it = vec.begin(); it != vec.end(); it++) { } I don't think a lot of people think in terms of iterators, but I've learned to adapt. - S 50 cups of coffee and you know it's on!
-
I can tell you why I don't use the algorithms too much * The VC 6 STL docs blow so I haven't read them much and don't know what algorithm functions exist * The STL naming scheme sucks so it's hard to figure out what some functions are for from just their name (and the docs aren't much help, see 1. I mean, seriously, WTF does "
bind2nd
" do??) * Most of the time when I do use algorithms, it involves writing a special-case functor for just that usage, which is workable but just feels sloppy. I know aboutmem_fun_ref
and the like, but I haven't taken the time to figure out how they work. * Instead of fighting with the docs, I'll just write a for loop and be done with it--Mike-- Visual C++ MVP :cool: LINKS~! Ericahist | PimpFish | CP SearchBar v3.0 | C++ Forum FAQ
I agree with some but not all of your critisims.
Michael Dunn wrote:
The VC 6 STL docs blow so I haven't read them much and don't know what algorithm functions exist
I think in general MS documentation sucks. But STL is part of C++ and you shouldn't look to MS to teach you C++; the same applies to STL.
Michael Dunn wrote:
The STL naming scheme sucks so it's hard to figure out what some functions are for from just their name (and the docs aren't much help, see 1. I mean, seriously, WTF does "bind2nd" do??)
I'm not sure about this one. I admit STL has a price of admission but I've got nothing against the naming scheme. I mean, what does
EnterCriticalSection
do just from the name? Names should be descriptive but the names can be scoped by the general topic to which they apply - in this case synchronization primitives.Michael Dunn wrote:
Most of the time when I do use algorithms, it involves writing a special-case functor for just that usage, which is workable but just feels sloppy
I agree this can be a pain. Most times the work involved in writing a functor is not a problem as it can be reused multiple times. There are times however when you find yourself writing a one off functor which just complicates the code. The addition of Lambda functions to C++ would help here. The Boost.Lamda library is also interesting.
Michael Dunn wrote:
Instead of fighting with the docs, I'll just write a for loop and be done with it
This only works for the simplest of the algoritms like
copy
orfor_each
. What about things such asbinary_search
andrandom_shuffle
?Steve
-
I can tell you why I don't use the algorithms too much * The VC 6 STL docs blow so I haven't read them much and don't know what algorithm functions exist * The STL naming scheme sucks so it's hard to figure out what some functions are for from just their name (and the docs aren't much help, see 1. I mean, seriously, WTF does "
bind2nd
" do??) * Most of the time when I do use algorithms, it involves writing a special-case functor for just that usage, which is workable but just feels sloppy. I know aboutmem_fun_ref
and the like, but I haven't taken the time to figure out how they work. * Instead of fighting with the docs, I'll just write a for loop and be done with it--Mike-- Visual C++ MVP :cool: LINKS~! Ericahist | PimpFish | CP SearchBar v3.0 | C++ Forum FAQ
Michael Dunn wrote:
The VC 6 STL docs blow
Along with VC6 STL and the VC6 compiler (where templates are concerned) - which is why I like VC2003 so much. I do 'raw' C++, command line tools rather than GUI tools, so any MFC failings aren't too important for me.
Michael Dunn wrote:
t involves writing a special-case functor for just that usage
And that's why Boost.Lambda[^] is a library I use a lot... Ok, OK, I admit it, I'm just an STL fanboy :)
-
This makes much more sense to me (but I'm old school): vector vec; for (int i = 0; i < vec.size(); i++) { } than vector vec; vector::iterator it; for (it = vec.begin(); it != vec.end(); it++) { } I don't think a lot of people think in terms of iterators, but I've learned to adapt. - S 50 cups of coffee and you know it's on!
This is how I'd do it:
typedef std::vector<whatever> collection_t; collection_t coll; // Fill 'coll' here... for (collection_t::iterator i=vec.begin(); i!=vec.end(); ++i) { // Do stuff here... }
Now you can change the type of the collection by altering one line. For example to use alist
instead:typedef std::list<whatever> collection_t;
This is an expression of the general design principle that one design decision should be expressed in only one place, if possible. In this case the choice of collection type only requires a change in one location and not scattered places throughout the code. STL and iterators don't make this happen automatically but they provide the abstractions to make this sort of thing possible. In your first example you'd have to make changes in multiple places including inside the loop aslist
s don't support indexing.Steve
-
I can tell you why I don't use the algorithms too much * The VC 6 STL docs blow so I haven't read them much and don't know what algorithm functions exist * The STL naming scheme sucks so it's hard to figure out what some functions are for from just their name (and the docs aren't much help, see 1. I mean, seriously, WTF does "
bind2nd
" do??) * Most of the time when I do use algorithms, it involves writing a special-case functor for just that usage, which is workable but just feels sloppy. I know aboutmem_fun_ref
and the like, but I haven't taken the time to figure out how they work. * Instead of fighting with the docs, I'll just write a for loop and be done with it--Mike-- Visual C++ MVP :cool: LINKS~! Ericahist | PimpFish | CP SearchBar v3.0 | C++ Forum FAQ
Michael Dunn wrote:
The VC 6 STL docs blow so I haven't read them much and don't know what algorithm functions exist
See, this kind of comment is the kind that surprises me. My undergraduate textbook for my Data Structures and Algorithms class went over all that very well ... and Bjarne's book covers them fairly well, also. Seems to me those would be required reading for any C++ programmer (just like Petzold and Prosise are generally considered to be required reading for doing Windows programming in C++).
Michael Dunn wrote:
The STL naming scheme sucks so it's hard to figure out what some functions are for from just their name (and the docs aren't much help, see 1. I mean, seriously, WTF does "bind2nd" do??)
It does exactly what it says it does: binds the second argument to what you pass in to bind2nd. Namely, when passing a binary function/functor into an algorithm that is expecting a unary function/functor, it allows you to bind the second value of the function call to something outside the algorithm. The syntax is a bit tough to get the hang of at first, but it makes sense once you get use to it.
Michael Dunn wrote:
Most of the time when I do use algorithms, it involves writing a special-case functor for just that usage, which is workable but just feels sloppy. I know about mem_fun_ref and the like, but I haven't taken the time to figure out how they work.
There are some things where functors are useful (a general case Deleter functor, for example), but most of the time, I just write a simple function that isn't a member function to do whatever operation I was intending to do in the loop, and then use for_each or transform. It doesn't have to be a functor to be passed into an algorithm.
Michael Dunn wrote:
Instead of fighting with the docs, I'll just write a for loop and be done with it
So, what you are saying is that you basically ignore principles of good software engineering practices with regard to code reuse because you are too lazy to learn to use the standard library's power?
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac
-
This makes much more sense to me (but I'm old school): vector vec; for (int i = 0; i < vec.size(); i++) { } than vector vec; vector::iterator it; for (it = vec.begin(); it != vec.end(); it++) { } I don't think a lot of people think in terms of iterators, but I've learned to adapt. - S 50 cups of coffee and you know it's on!
Steve Echols wrote:
This makes much more sense to me (but I'm old school): vector vec; for (int i = 0; i < vec.size(); i++) { } than vector vec; vector::iterator it; for (it = vec.begin(); it != vec.end(); it++) { }
See, but neither is "correct". Assume you are calling
DoSomething(const whatever& w)
for each iteration of the loop. The entire loop can be written as follows:vector<whatever> vec; // fill it somewhere // DoSomething is declared and implemented somewhere for_each(vec.begin(), vec.end(), DoSomething);
Using iterators in place of the index doesn't buy you anything in terms of taking advantage of the pre-made algorithms STL gives you.
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac
-
This is how I'd do it:
typedef std::vector<whatever> collection_t; collection_t coll; // Fill 'coll' here... for (collection_t::iterator i=vec.begin(); i!=vec.end(); ++i) { // Do stuff here... }
Now you can change the type of the collection by altering one line. For example to use alist
instead:typedef std::list<whatever> collection_t;
This is an expression of the general design principle that one design decision should be expressed in only one place, if possible. In this case the choice of collection type only requires a change in one location and not scattered places throughout the code. STL and iterators don't make this happen automatically but they provide the abstractions to make this sort of thing possible. In your first example you'd have to make changes in multiple places including inside the loop aslist
s don't support indexing.Steve
Stephen Hewitt wrote:
typedef std::vector collection_t; collection_t coll; // Fill 'coll' here... for (collection_t::iterator i=vec.begin(); i!=vec.end(); ++i) { // Do stuff here... }
That still doesn't use STL's algorithms. Granted, it is reimplementing a for_each or a transform (depending on what you do in the loop), but the fact is it is still reimplementing it needlessly.
Stephen Hewitt wrote:
This is an expression of the general design principle that one design decision should be expressed in only one place, if possible. In this case the choice of collection type only requires a change in one location and not scattered places throughout the code. STL and iterators don't make this happen automatically but they provide the abstractions to make this sort of thing possible.
Take a look at Scott Meyer's "Effective STL" for why this isn't really true.
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac
-
I continuously see people asking questions about code they have written that involves loops for things such as pulling in input, displaying output, transforming data in a collection, etc. All of which can be done using STL algorithms using much less code, but instead is done using (usually) complex code written by the programmer asking the question. Why is it that so many people don't use the STL algorithms?
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac
Zac Howland wrote:
Why is it that so many people don't use the STL algorithms?
When I first started using STL for some time I just used the basic containers and looped over them. The VC++ 6 docs were good enough to get going with this kind of thing. Algorithms and function objects seemed rather mysterious. But once I found out what they were about then I started using them. The trigger for me was having to maintain code that used STL heavily. Then I was forced to understand it. I also bought Stroustup 3rd ed and Josuttis. I didn't do CS at college. My background is in civil engineering. I guess there are probably some old school C/C++ devs who cannot see any reason to move beyond what they consider to be tried-and-tested. This basically means when you maintain their code you are typically met with a mixture of error-prone C and old-style C++.
Kevin
-
I can tell you why I don't use the algorithms too much * The VC 6 STL docs blow so I haven't read them much and don't know what algorithm functions exist * The STL naming scheme sucks so it's hard to figure out what some functions are for from just their name (and the docs aren't much help, see 1. I mean, seriously, WTF does "
bind2nd
" do??) * Most of the time when I do use algorithms, it involves writing a special-case functor for just that usage, which is workable but just feels sloppy. I know aboutmem_fun_ref
and the like, but I haven't taken the time to figure out how they work. * Instead of fighting with the docs, I'll just write a for loop and be done with it--Mike-- Visual C++ MVP :cool: LINKS~! Ericahist | PimpFish | CP SearchBar v3.0 | C++ Forum FAQ
Michael Dunn wrote:
The VC 6 STL docs blow so I haven't read them much and don't know what algorithm functions exist
Perhaps. But I found them good enough to get going quite far with STL. I had used STL for some time before buying a book on it.
Kevin
-
Zac Howland wrote:
Why is it that so many people don't use the STL algorithms?
When I first started using STL for some time I just used the basic containers and looped over them. The VC++ 6 docs were good enough to get going with this kind of thing. Algorithms and function objects seemed rather mysterious. But once I found out what they were about then I started using them. The trigger for me was having to maintain code that used STL heavily. Then I was forced to understand it. I also bought Stroustup 3rd ed and Josuttis. I didn't do CS at college. My background is in civil engineering. I guess there are probably some old school C/C++ devs who cannot see any reason to move beyond what they consider to be tried-and-tested. This basically means when you maintain their code you are typically met with a mixture of error-prone C and old-style C++.
Kevin
Kevin McFarlane wrote:
I guess there are probably some old school C/C++ devs who cannot see any reason to move beyond what they consider to be tried-and-tested. This basically means when you maintain their code you are typically met with a mixture of error-prone C and old-style C++.
I can understand that (even though I disagree with the reasoning, "I've always done it this way ..." -- that isn't a reason in my opinion), but many of the questions I've seen are coming from either those that are still in college or those that are fresh out of college. I can almost understand seeing it from someone still in college if they are a first or second year CS or CPE major. But 3rd year+?
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac
-
Kevin McFarlane wrote:
I guess there are probably some old school C/C++ devs who cannot see any reason to move beyond what they consider to be tried-and-tested. This basically means when you maintain their code you are typically met with a mixture of error-prone C and old-style C++.
I can understand that (even though I disagree with the reasoning, "I've always done it this way ..." -- that isn't a reason in my opinion), but many of the questions I've seen are coming from either those that are still in college or those that are fresh out of college. I can almost understand seeing it from someone still in college if they are a first or second year CS or CPE major. But 3rd year+?
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac
Zac Howland wrote:
I can understand that (even though I disagree with the reasoning, "I've always done it this way ..." -- that isn't a reason in my opinion)
I fully agree. I was just reporting how these guys think.:)
Zac Howland wrote:
many of the questions I've seen are coming from either those that are still in college or those that are fresh out of college.
Doesn't say much for the state of CS courses does it?
Kevin
-
Zac Howland wrote:
I can understand that (even though I disagree with the reasoning, "I've always done it this way ..." -- that isn't a reason in my opinion)
I fully agree. I was just reporting how these guys think.:)
Zac Howland wrote:
many of the questions I've seen are coming from either those that are still in college or those that are fresh out of college.
Doesn't say much for the state of CS courses does it?
Kevin
Kevin McFarlane wrote:
Doesn't say much for the state of CS courses does it?
No, actually, it scares me. These guys are making my degree less valuable :sigh: Of course, then there are the colleges that stopped teaching C/C++ as the primary language for CS majors and switch over to Java. I have yet to meet one of them that understands basic (language-independent) design principles because Java doesn't force you to learn them.
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac
-
Stephen Hewitt wrote:
typedef std::vector collection_t; collection_t coll; // Fill 'coll' here... for (collection_t::iterator i=vec.begin(); i!=vec.end(); ++i) { // Do stuff here... }
That still doesn't use STL's algorithms. Granted, it is reimplementing a for_each or a transform (depending on what you do in the loop), but the fact is it is still reimplementing it needlessly.
Stephen Hewitt wrote:
This is an expression of the general design principle that one design decision should be expressed in only one place, if possible. In this case the choice of collection type only requires a change in one location and not scattered places throughout the code. STL and iterators don't make this happen automatically but they provide the abstractions to make this sort of thing possible.
Take a look at Scott Meyer's "Effective STL" for why this isn't really true.
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac
Zac Howland wrote:
That still doesn't use STL's algorithms. Granted, it is reimplementing a for_each or a transform (depending on what you do in the loop), but the fact is it is still reimplementing it needlessly.
No this loop doesn't use algorithms, just iterators. I could have used the
for_each
algorithm but this would have been, depending on what I'm doing inside the loop, an example of Michael Dunn's objection to STL: having to write a "one off" functor. If what you're doing in the loop is simple or unique it is often better to use a hand written loop instead of usingfor_each
. This is the exact reason why suggestions to include lambda functions in C++ and libraries like Boost.Lambda were written. The point I was trying to get at was that using iterators in preference to direct indexing increases you ability to make alterations to the code. For example is this really necessary or "good form":template <typename T> struct square_plus_one : std::unary_function<T, T> { T operator()(const T &v) const { return (v*v)+1; } }; int main(int argc, char* argv[]) { typedef std::vector<int> collection_t; collection_t coll; // Fill 'coll' here... std::for_each(coll.begin(), coll.end(), square_plus_one()); return 0; }
I would argue the following is better and the price we pay (re-implementing the loop) is of no real consequence in this case:typedef std::vector<int> collection_t; collection_t coll; // Fill 'coll' here... for (collection_t::iterator i=vec.begin(); i!=vec.end(); ++i) { *i = ((*i)*(*1))+1; }
Zac Howland wrote:
Take a look at Scott Meyer's "Effective STL" for why this isn't really true.
What's not true? If I want to see if I get better performance or use less memory using a
std::list
I simply change one line - this is a fact. Not many people will think it's better to have to make multiple scattered changes and run the risk of introducing an error somewhere along the way. If you've got a specific point make it here as opposed to referring to a book but giving no clue to what to mean -
Zac Howland wrote:
That still doesn't use STL's algorithms. Granted, it is reimplementing a for_each or a transform (depending on what you do in the loop), but the fact is it is still reimplementing it needlessly.
No this loop doesn't use algorithms, just iterators. I could have used the
for_each
algorithm but this would have been, depending on what I'm doing inside the loop, an example of Michael Dunn's objection to STL: having to write a "one off" functor. If what you're doing in the loop is simple or unique it is often better to use a hand written loop instead of usingfor_each
. This is the exact reason why suggestions to include lambda functions in C++ and libraries like Boost.Lambda were written. The point I was trying to get at was that using iterators in preference to direct indexing increases you ability to make alterations to the code. For example is this really necessary or "good form":template <typename T> struct square_plus_one : std::unary_function<T, T> { T operator()(const T &v) const { return (v*v)+1; } }; int main(int argc, char* argv[]) { typedef std::vector<int> collection_t; collection_t coll; // Fill 'coll' here... std::for_each(coll.begin(), coll.end(), square_plus_one()); return 0; }
I would argue the following is better and the price we pay (re-implementing the loop) is of no real consequence in this case:typedef std::vector<int> collection_t; collection_t coll; // Fill 'coll' here... for (collection_t::iterator i=vec.begin(); i!=vec.end(); ++i) { *i = ((*i)*(*1))+1; }
Zac Howland wrote:
Take a look at Scott Meyer's "Effective STL" for why this isn't really true.
What's not true? If I want to see if I get better performance or use less memory using a
std::list
I simply change one line - this is a fact. Not many people will think it's better to have to make multiple scattered changes and run the risk of introducing an error somewhere along the way. If you've got a specific point make it here as opposed to referring to a book but giving no clue to what to meanStephen Hewitt wrote:
Michael Dunn's objection to STL: having to write a "one off" functor.
You don't have to write a functor to use for_each, nor most of the other algorithms. Using your own example (and by the way, your for_each example actually does nothing but waste CPU cycles as written), the following works perfectly fine:
template<class T> T square_plus_one(const T& i) { return (i * i + 1); } int main() { vector<int> intVec; // fill vector here transform(intVec.begin(), intVec.end(), intVec.begin(), square_plus_one<int> ) ; return 0; }
Granted, the Lamda library makes this even easier, and I fully support the use of it. However, for most common loops, this really isn't that complex.
Stephen Hewitt wrote:
What's not true? If I want to see if I get better performance or use less memory using a std::list I simply change one line - this is a fact. Not many people will think it's better to have to make multiple scattered changes and run the risk of introducing an error somewhere along the way. If you've got a specific point make it here as opposed to referring to a book but giving no clue to what to mean.
What I meant is that the containers are not completely interchangible. For some simple things such as iterating through them, they are designed to be the same to make use of the algorithms. However, things like insertion, deletion, allocation of space, etc ... many of them are different (have different function names, don't have certain functions, etc). I directed you to the book because he gives a much better explanation that I could hope to offer on this forum (at least without plaugerizing the book).
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac
-
Stephen Hewitt wrote:
Michael Dunn's objection to STL: having to write a "one off" functor.
You don't have to write a functor to use for_each, nor most of the other algorithms. Using your own example (and by the way, your for_each example actually does nothing but waste CPU cycles as written), the following works perfectly fine:
template<class T> T square_plus_one(const T& i) { return (i * i + 1); } int main() { vector<int> intVec; // fill vector here transform(intVec.begin(), intVec.end(), intVec.begin(), square_plus_one<int> ) ; return 0; }
Granted, the Lamda library makes this even easier, and I fully support the use of it. However, for most common loops, this really isn't that complex.
Stephen Hewitt wrote:
What's not true? If I want to see if I get better performance or use less memory using a std::list I simply change one line - this is a fact. Not many people will think it's better to have to make multiple scattered changes and run the risk of introducing an error somewhere along the way. If you've got a specific point make it here as opposed to referring to a book but giving no clue to what to mean.
What I meant is that the containers are not completely interchangible. For some simple things such as iterating through them, they are designed to be the same to make use of the algorithms. However, things like insertion, deletion, allocation of space, etc ... many of them are different (have different function names, don't have certain functions, etc). I directed you to the book because he gives a much better explanation that I could hope to offer on this forum (at least without plaugerizing the book).
If you decide to become a software engineer, you are signing up to have a 1/2" piece of silicon tell you exactly how stupid you really are for 8 hours a day, 5 days a week Zac
Zac Howland wrote:
You don't have to write a functor to use for_each, nor most of the other algorithms. Using your own example (and by the way, your for_each example actually does nothing but waste CPU cycles as written), the following works perfectly fine:
Firstly in your example you've written a "one off" function instead of a "one off" functor, the same objection applies in this case. Secondly, your code doesn't seem to work. Try compiling this:
#include <iostream> #include <vector> #include <algorithm> #include <iterator> template <typename T> T square_plus_one(const T& i) { return (i * i + 1); } int main() { // For notational convenience. using namespace std; vector<int> intVec; // Fill vector. for (int i=1; i<=10; ++i) { intVec.push_back(i); } // Transform the data. transform(intVec.begin(), intVec.end(), intVec.begin(), square_plus_one<int> ); // Output the results. copy(intVec.begin(), intVec.end(), ostream_iterator<int>(cout, " ")); cout << endl; return 0; }
I get the following error: "CommandLine.obj : error LNK2001: unresolved external symbol "int __cdecl square_plus_one(int const &)" (?square_plus_one@@YAHABH@Z)" I'm not sure if this is a compiler bug or what (MSVC6) but regardless it's a problem. As to the “wasted cycles” I concede that I made a mistake in that the results of my calculations are never used (oops). Functors are no less efficient in general however, consider the following. I've altered the code as follows:// Changed function so we compile and made inline. inline int square_plus_one(int i) { return (i * i + 1); } // Added a functor version for comparison: struct functor_square_plus_one : std::unary_function<int, int> { int operator()(int i) const { return (i * i + 1); } }; // Altered transform: transform(intVec.begin(), intVec.end(), intVec.begin(), square_plus_one) ; // Added call to functor ver