The C++ STL: How to Harness Its Power
Sometimes, as a software engineer, one has to deal with code we would rather not. "What were they thinking?" is a common sentiment. In my experience, this seems to be more exacerbated in C++, where it's much easier to do the wrong thing and re-implement something ourselves instead of using what's available to us by the standard library, especially the Standard Template Library (STL).
In C++ in particular, it's very easy to fall into the mindset that the STL “has nothing really useful” or “can't do what I want.” But in reality, for a number of common, real-world algorithms and expressions, it's a great toolset. In this blog post, I want to give a quick refresher on the STL, and show how proper STL usage would have greatly simplified now-legacy code at Accusoft.
Although I admit that C++ STL isn't as "rich" as other standard libraries such as C#'s, that's no reason to write it off. In some ways, it even provides more power, like std::adjacent_find. I also think the STL is a more unique in that it isn't as intuitive to understand its power. I believe this is because the STL algorithms tend to be very generic and don't always lend themselves to instantly knowing when to use what. So how does one go about effective STL use? I've found it comes down to a couple key sequential thought processes:
- Become familiar with <algorithm>, <numeric>, and the STL containers in particular. This will allow one to realize the majority of what is available before programming.
- Before writing code using containers, model the problem down to its core. This is through verbiage such as "all this function is doing is…" and "I just need to check that…" you may find there is either a specific algorithm for what you're doing, such as std::nth_element and the set functions such as std::set_union, or the case is commonly handled with things such as std::all_of.
- When writing, avoid raw loops where possible. C++ programmers may be familiar with the term "raw pointers" and to prefer unique_ptr, shared_ptr, and so on, but "raw loops" is a concept that, if you write a C for- or while-loop, there is likely a chance a STL algorithms can do the same for you with less code and less chance to make mistakes.
Not using raw loops has the advantage that STL functions can only do one thing. In many codebases, it seems the temptation to just modify an existing loop to check multiple things is common. If another loop to check something is simply a linear operation, unless you are doing super critical high performance applications, I believe it's worth it to maintain better readability.
The next sections will put these thought processes to work on a number of real code examples with steps on how to improve their effectiveness using the Standard Template Library. Read on!
James Waugh began his career at Accusoft in 2016, where he started in technical support. Since then, he obtained a Software Engineer III role on Accusoft's SDK products, where he focuses on machine learning, PDF, and image processing technologies. A graduate of the University of South Florida, James holds a Computer Engineering degree. He also attends local technology meetups such as Barcamp Tampa regularly. Outside the office, James enjoys taking his classic Chevrolet Bel Air to car shows and practicing Japanese.