You might not have even heard of parameter packs or variadic templates before, but if you’ve worked with C++ templates for a while, chances are at some point you’ve wanted the functionality they provide. This post provides a few practical examples showing some of the problems they solve and techniques they enable.
C++
Topics relating to the C++ language, techniques, etc.
Lambdas for lunch
Alright, so lambdas in C++ are cool and we’ve been coding with one arm tied behind our back all this time. C++11 brought us this wonderful goodness, which is great, but just how do you actually use them? No messing around, let’s jump right in!
Iterating over an enum
The enum
feature of C/C++ is far from new. It is very useful for defining a specific set of values that a simple integer may take, which can lead to clearer, more concise code when used appropriately. Many compilers are capable of warning about common errors associated with enum
use, such as not including case
statements for all possible enum
values in a switch
statement that has no default
clause. In many respects, an enum
acts like a set, but being essentially just a glorified int
, it lacks any of the container features of something like std::set
.
The developer typically faces a tradeoff between performance and functionality when deciding between an enum
or some kind of set-like container. There are some (often common) situations, however, where an enum
can still be treated like a container, thanks to features made available in C++11.
C++ list initialization
Containers
Consider this very typical piece of C/C++ code for creating an array of integers from a list of specified values (called a braced initializer):
const int[] someInts = {23, 10, 5, 17};
This is simple and works well where a plain int
array is needed, but sometimes we want to do something similar with STL containers.
Container iteration with C++11
C++11 introduced some features which make working with STL containers much easier. One common situation is the need to iterate over a container and to perform some operation(s) on each item. Consider the following typical example:
std::vector<SomeType> container;
// ...
for(std::vector<SomeType>::iterator iter = container.begin();
iter != container.end();
++iter)
{
const SomeType& item = *iter;
// ...
}
This syntax has a couple of drawbacks:
- It is rather verbose
- Every aspect of the container’s type needs to be included in the definition of
iter