• Advertisement
Sign in to follow this  

Pros/Cons of coding alternatives to std::algorithm?

This topic is 683 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Sorry if this question has been asked before, the search didn't turn up anything.

I'm wondering about the pros/cons of adding alternatives to the std::algorithm library to my codebase. I've done this in a couple of beginner projects, but I always felt like it's probably a bad practice to do so. Now I'm at the point again where I feel that I could write my code alot more clearly just by adding a few methods.

For example, consider the following:

struct Foo { void bar(); };

// I want to call bar on all foos.
std::map<int, Foo> my_foos;

// using for_each from std::algorithm
std::for_each(my_foos.begin(), my_foos.end(), [](auto& iter){
     iter.second.bar();
};

// but consider how much nicer it could be
for_each_value(my_foos, &Foo::bar);

In the above example, I have an alternative that:

- applies a function to the values only

- takes the name of the collection instead of having to write both iterators

- can use a member function instead of a lamba as we are iterating over the values only

 

So overall, is it okay to do this?

Share this post


Link to post
Share on other sites
Advertisement

For example, consider the following:

// using for_each from std::algorithm
std::for_each(my_foos.begin(), my_foos.end(), [](auto& iter){
     iter.second.bar();
};

 

Since you're already using c++11, consider also c++11 way:

for(auto& iter: my_foos)
{
     iter.second.bar();
}

Share this post


Link to post
Share on other sites

Thanks for the replies.

 

I usually end up using those ranged-for loops, but I'd prefer to use the for_each if it wasn't so much to type. In Java I use it all the time because you can do exactly the thing I gave as an example:

HashMap<Integer, Foo> myFoos = new HashMap<>();

myFoos.values().forEach(Foo::bar); // not 100% sure about syntax but something like this

About the data structures, alot of times I will need data which I can access by some name or id, but where I really only care about the value when looping over it.

Share this post


Link to post
Share on other sites

Generally speaking, I think you should use the least flexible construct to do a given task, because it tends to yield code that's easier to read.  In that light, I usually prefer the range-for if I'm iterating over a container, but I'll use for_each() if I need to iterate over a subset of the container, simply because that's the extent of the extra flexibility you get (outside of boost kung fu).  If you need to do a non-trivial linear traversal like iterating over every even element, I'd use a raw for loop.

 

The above is for standard language and library things, though.  Regarding writing your own "iterate-over-this-map-and-perform-a-function-on-every-value" algorithm, that feels like it's so special-purpose that you might want to reconsider your choice of data structure.  How often do you loop over it versus access by name or id?  If you rarely loop, the verbose loop in your OP ought to be fine.  If you loop frequently, it might be worth using a vector instead (which has a much cleaner iteration) and just "accessing" using std::find.
 

Edited by SeraphLance

Share this post


Link to post
Share on other sites
I would recommend using for_each until you get the habit of looking at <algorithm> before implementing your own.
There are some of very nice function like rotate, stable partition that goes almost unnoticed. Of course there is likely no difference in performance between a range for and for_each and there is a big temptation to roll your own version of replace_if or fill since they are trivial but you'll probably win a lot if you practice some functional programming.

In addition parallel version of for_each may be added to c++ 17 meaning that you just have to change the function name in your calls if you think they can benefit from it.

Share this post


Link to post
Share on other sites

Another fun collection are the heap operations. While people are generally more comfortable working with the bigger containers that maintain order, heaps have many useful properties and used with the wrapper for priority_queues. That's useful for anything with priorities like the typical A* implementation or any kind of processing involving the first N, or nearest N, and similar. Quite a few of the more CS-intensive algorithms rely on the heap data structure.

 

In any event, prefer the built in functionality if you can make it work.  If not, look for other libraries like Boost or EASTL.  Try not to re-invent or re-implement the wheel.

Share this post


Link to post
Share on other sites

Another fun collection are the heap operations. While people are generally more comfortable working with the bigger containers that maintain order, heaps have many useful properties and used with the wrapper for priority_queues. That's useful for anything with priorities like the typical A* implementation or any kind of processing involving the first N, or nearest N, and similar. Quite a few of the more CS-intensive algorithms rely on the heap data structure.

 

In any event, prefer the built in functionality if you can make it work.  If not, look for other libraries like Boost or EASTL.  Try not to re-invent or re-implement the wheel.

Every C++ dev should have Boost.  Granted this was more-so a few years ago, less so now that nearly 1/2 of Boost has been added to the standard library; but Its still exceptionally useful.

Share this post


Link to post
Share on other sites

"I always felt like it's probably a bad practice to do so."

 

It's not if it does the job. I get to say it again; You don't need code to run as fast as possible -- you only need fast enough

 

Build it using the BIGGEST tools you can find -- the less work you have to do the sooner you can get a project done, profile it, then replace only the sections that mean you're not hitting your target.

 

Your goal is a completed project, not a tiny section of very-very-very-very spiffy code.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement