September 22, 2015 - Daniel Kolesa

3 Reasons You Should Use C++11

This article is part 2 of a 4 part series on the benefits of the C++11 revision of the C++ programming language

C++11 is the first update to the standard since 2003 and brings many significant features into the language. This article covers three of the most valuable features of C++11: variadic templates, type and template aliases, and type inference.

Variadic templates provide functionality to handle type packs, allowing you to create templates with a variable number of template parameters as well as true, type safe variadic functions. The new type alias syntax allows for better readability and templating. Type inference lets the language deduce types of expressions, thus reducing verbosity and removing the need to explicitly specify types in many places.

Variadic Templates

In my opinion variadic templates are the single most useful feature introduced in the new standard. They provide the ability to create type packs, allowing for extended template metaprogramming, but more significantly, sane variadic functions.

You might be asking, what’s wrong with classic style variadic functions? Well,┬áC++ inherited them from C and they utilize the stdarg.h header to manipulate va_lists. The va_arg macro provides the ability to retrieve the next value in the variadic parameter pack. This approach has two main problems, a lack of type awareness and an inconvenient API.

Lack of Type Awareness

In the case of something like printf("%d\n", 5); you have to specify the type as part of the format string. This system almost completely erases static type checking, leaving a vague object whose type needs to be known beforehand. This is bug prone, and is generally inconvenient, especially in a language that allows extensive static metaprogramming. Additionally, optimizing such functions becomes more difficult.

Inconvenient API

Have you ever noticed how every variadic function in C provides a variant for the actual parameter pack as well as for va_list? This could all be solved if variadic functions were type safe and weren’t required to have a special API for handling parameter packs.

The variadic API is also poorly defined when it comes to va_list copies. This causes inconveniences across compilers, because every toolchain chooses a different internal representation of va_list, with wildly different semantics. This is partially addressed in C99 with the va_copy macro, which hides some of the awkward semantic differences, but is still far from ideal.

C++11 Variadic Templates To the Rescue!

C++11 variadic templates solve both problems. They don’t need an API, as they’re a language feature; and they’re completely type safe, since the function is a template and will expand at compile time into a non-variadic variant.

So, let’s declare a C++11 variadic function, shall we? Let’s define an example function that will call something over each argument.

Unfortunately, it’s not possible to iterate over parameter packs. If you think about it, there really can’t be. We have a heterogeneous tuple of types, and the only way to handle this is through recursion. Additionally, a parameter pack can be empty so we need to declare a “sentinel” function for when nothing is passed (i.e. when the args pack is empty) to stop the traversal.

One final thing to note is that when passing argument packs like this, they can be annotated as references, const references, or rvalue references just like if they were a single argument. This will get applied to every type in the pack. In this case, we utilize perfect forwarding with rvalue references (will be described in the next article).

To retrieve the size of a pack, you can use sizeof...(A).

Variadic functions are not the only use for variadic templates. You can use them within your template metaprogramming algorithms and treat them just like standard template types. With the exception that it isn’t possible to actually use type packs directly (i.e. you can’t make an alias to them). For example, consider the creation of a template that allows the construction of a function pointer type with arbitrary args and return type. It’s easy:

New Type Aliases and Template Aliases

C allows you to create type aliases using the typedef keyword. It’s messy and allows multiple syntaxes. For example, these two are identical:

It gets worse for function pointers:

Additionally, it doesn’t allow templating. So if you want to create an alias for a structure that fills in some template types and leaves the others to the user, you’re out of luck. Fortunately, C++11 introduced a new syntax:

Isn’t it cleaner? For function pointers, nothing changes:

And you can template it as easily:

It also allows type traits to use syntax that is much nicer. Consider for example std::remove_cv. To get the type, the code will be quite ugly:

Template aliases allow this to be turned into a much nicer syntax:

C++14 adds these aliases into the standard library. In C++11, they have to be created manually.

Type Inference

C++11 finally introduced type inference. However it’s only local type inference, so it can’t do complicated whole-program analysis. With that said, for the purposes of the language it’s good enough; global inference requires careful design from the start anyway and wouldn’t work very well.

The simplest kind is to use the auto keyword:

The type of x will be inferred automatically. This is not the only kind of type inference in the language. It now possible to use decltype() to infer types of expressions. For example:

You can use decltype() in any place a type would be expected. It also integrates neatly with expression SFINAE, which will be covered later in this series..

C++11 also allows trailing return type syntax. Using this, it’s possible to write functions like this:

Replacing the auto would be insufficient, because the variables that are being manipulated don’t exist yet as they’re yet to be parsed. Speaking of which, in C++14, it’s possible to drop the decltype() entirely, as the language can just figure it out.

It isn’t always possible to access variables. Using std::declval(), it’s possible to declare placeholders of any type to be used in constant expressions; there is no runtime representation of declval results.

This will resolve to return type of a method foo(x) called on const reference to MyObject with an int parameter.

Onward to More C++11!

There are plenty of reasons to build software with C++11, these are just a handful of the most important. In particular, variadic templates are a very significant feature that developers can benefit from greatly by gaining true type safety for variadic functions as well as a cleaner API. Additionally, New type aliases help make code more readable, and type inference reduces verbosity, allowing for nicer more concise code.

But wait, there’s more! Part three of the series will cover four additional major features of C++11: lambda expressions, expression SFINAE, rvalue references and move semantics, and constexpr. Stay tuned!

Image Credits: Tom Small
Daniel Kolesa

About Daniel Kolesa

Daniel Kolesa has been contributing to open source since 2007 and has worked with a handful open source projects. His work has been primarily on Enlightenment, starting in late 2008 with his main focus being the Enlightenment Foundation Libraries. In January 2014 he moved from the Czech Republic to the UK and joined the Samsung Open Source Group to focus more on the EFL and eventually became a maintainer of several core EFL components including Eolian and Elua. He is also a video game developer, maintaining his own OctaForge 3D engine. FInally, he is also a functional programming fan, having worked with languages such as Rust and OCaml, and having designed his own programming languages and compiler tech.

Image Credits: Tom Small

Development c++11 /

Leave a Reply

Your email address will not be published. Required fields are marked *

Comments Protected by WP-SpamShield Anti-Spam