Blog 6 min read

Learn the new C++11 features from the Folly source code.

Share this article
Learn the new C++11 features from the Folly source code.

Six years ago Facebook released its C++ library named Folly, a large collection of reusable C++ library components that are used extensively internally at Facebook.

But many mature open-source C++ libraries already exist, so why introduce another one? Here are the motivations behind its creation, as explained on their website:

Folly (acronymed loosely after Facebook Open Source Library) is a library of C++11 components designed with practicality and efficiency in mind. It complements (as opposed to competing against) offerings such as Boost and of course std. In fact, we embark on defining our own component only when something we need is either not available, or does not meet the needed performance profile.

Here's, for example, a detailed explanation of why Folly introduced another vector class, FBVector. As the Folly developers claim, it is a library of C++11 components—a claim that is fully supported by a look at the source code: the C++11 features are extensively used, and moreover, almost all new C++11 features are used.

When C++0x was announced a few years ago, I thought it would not have much impact on the C++ language, but I was wrong. Take a look at this code snippet from Folly — it looks like it was developed using a new language.

c0

The same observation applies to almost all of the Folly source code; its implementation looks different from C++03 source code.

For developers interested in mastering the new C++11 features, one of the best approaches is to see how mature libraries use them. Folly is a very good candidate for exploring the new features. Let's explore some of them in its source code.

1. auto

C++11 introduces type inference using the auto keyword, which means that the compiler infers the type of a variable at the point of declaration. Folly uses auto for almost all its variable declarations; here's an example from its source code.

c1

Using the auto keyword lets you spend less time explicitly writing types that the compiler already knows.

2. nullptr

The constant 0 traditionally served the dual role of an integer constant and a null pointer constant. C++11 corrects this by introducing a new keyword to serve as a distinguished null pointer constant: nullptr.

In the Folly source code, all null pointers are represented by the new keyword nullptr; there's no place where the constant 0 is used.

3. shared_ptr

Smart pointers are not a new concept; many libraries implemented them many years ago, the most popular one being boost::shared_ptr. What's new is their standardization — there is no longer any need to use an external library to work with smart pointers.

Folly uses the standardized shared pointer extensively; only a few raw pointers remain in its source code.

4. Strongly-typed enums

"Traditional" enums in C++ export their enumerators into the surrounding scope, which can lead to name collisions if two different enums in the same scope define enumerators with the same name. C++11 introduces scoped enumerations using the enum class syntax. They no longer export their enumerators into the surrounding scope. Moreover, we can now specify the underlying type of an enum.

c2

5. static assert

C++11 introduces a new way to test assertions at compile time, using the new keyword static_assert. This feature is very useful for adding conditions to template parameters, as shown in this template class from the Folly source code:

c3

6. Variadic template

A variadic template is a template that can take an arbitrary number of template arguments of any type. Both classes and functions can be variadic. Folly defines many variadic templates; here are two variadic template functions from the Folly source code:

c4

7. Range-based for loops

C++11 extends the for statement with range-based iteration over collections. It makes the code simpler and cleaner. Folly uses this feature extensively; here's an example from Folly.

c6

8. Initializer lists

In C++03, initializer lists apply only to arrays; in C++11, they are no longer limited to arrays. The mechanism for accepting a {}-list is a function (often a constructor) accepting an argument of type std::initializer_list<T>. Here's an example of a function accepting std::initializer_list as an argument.

c7

And here's how it's invoked.

c8

9. noexcept

If a function cannot throw an exception or if the program isn't written to handle exceptions thrown by a function, that function can be declared noexcept.

Here's an example from the Folly source code.

c9

10. move

C++11 introduced the concept of rvalue references (specified with &&) to differentiate a reference to an lvalue from a reference to an rvalue. An lvalue is an object that has a name, while an rvalue is an object that does not have a name (a temporary object). Move semantics allow modifying rvalues. To support this, C++11 introduces two new special member functions: the move constructor and the move assignment operator.

c12c10

Here's a good document that better explains the benefits of move semantics.

11. lambda

C++11 provides the ability to create anonymous functions, called lambda functions. You can refer here for more details about this new feature.

Folly uses them in many functions; here's an example from its source code:

c14

12. Explicitly defaulted and deleted special member functions

In C++03, the compiler provides, for classes that do not define them themselves, a default constructor, a copy constructor, a copy assignment operator (operator=), and a destructor. The programmer can override these defaults by defining custom versions. However, there is very little control over the creation of these defaults. Making a class inherently non-copyable, for example, requires declaring a private copy constructor and copy assignment operator without defining them. In C++11, certain features can be explicitly disabled. For example, the following type is non-copyable, which makes the code simpler and cleaner.

c15

13. override identifier

In C++03, it is possible to accidentally create a new virtual function when one intended to override a base class function. The override special identifier means that the compiler will check the base class(es) to see if there is a virtual function with this exact signature. If there is not, the compiler will report an error.

Folly uses this new feature extensively:

c18

14. std::thread

A thread class (std::thread) is provided, which takes a function object — and an optional series of arguments to pass to it — to run in the new thread. In C++11, working with threads is simpler; here is an example from the Folly source code showing the standard way to create a new thread:

c20

15. Unordered containers

An unordered container is a kind of hash table. C++11 offers four standard ones:

  • unordered_map
  • unordered_set
  • unordered_multimap
  • unordered_multiset

Folly uses these new containers in many places.

c21

Conclusion

Folly uses almost all the new C++11 features. Exploring its source code will give you a better understanding of the new C++ capabilities and how they are used in practice.

I encourage any C++ developer interested in C++11 to download the Folly source code and explore the power of modern C++.

Share this article