Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timer SALE ENDS IN
0 Days
:
00 Hours
:
00 Minutes
:
00 Seconds
Arrow up icon
GO TO TOP
Advanced C++ Programming Cookbook

You're reading from   Advanced C++ Programming Cookbook Become an expert C++ programmer by mastering concepts like templates, concurrency, and type deduction

Arrow left icon
Product type Paperback
Published in Jan 2020
Publisher Packt
ISBN-13 9781838559915
Length 454 pages
Edition 1st Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
 Quinn Quinn
Author Profile Icon Quinn
Quinn
Arrow right icon
View More author details
Toc

Table of Contents (15) Chapters Close

Preface 1. Getting Started with Library Development 2. Using Exceptions for Error Handling FREE CHAPTER 3. Implementing Move Semantics 4. Using Templates for Generic Programming 5. Concurrency and Synchronization 6. Optimizing Your Code for Performance 7. Debugging and Testing 8. Creating and Implementing Your Own Container 9. Exploring Type Erasure 10. An In-Depth Look at Dynamic Allocation 11. Common Patterns in C++ 12. A Closer Look at Type Deduction 13. Bonus - Using C++20 Features 14. Other Books You May Enjoy

How to namespace everything

When creating a library, it is important to namespace everything. Doing so ensures that of the APIs provided by the library cause name collisions with the user's code or with facilities provided by other libraries. In this recipe, we will demonstrate how to do this in our own libraries.  

Getting ready

As with all of the recipes in this chapter, ensure that all of the technical requirements have been met, including installing Ubuntu 18.04 or higher and running the following in a Terminal window:

> sudo apt-get install build-essential git cmake

This will ensure your operating system has the proper tools to compile and execute the examples in this recipe. Once you have done this, open a new Terminal. We will use this Terminal to download, compile, and run our examples.

How to do it...

You need to perform the following steps to complete this recipe:

  1. From a new Terminal, run the following to download the source code:
> cd ~/
> git clone https://github.com/PacktPublishing/Advanced-CPP-CookBook.git
> cd Advanced-CPP-CookBook/chapter01
  1. To compile the source code, run the following code:
> mkdir build && cd build
> cmake ..
> make recipe02_examples

  1. Once the source code has been compiled, you can execute each example in this recipe by running the following commands:
> ./recipe02_example01
The answer is: 42

> ./recipe02_example02
The answer is: 42

In the next section, we will step through each of these examples and explain what each example program does and how it relates to the lessons being taught in this recipe.

How it works...

C++ provides us with the ability to wrap code in a namespace, which simply adds the namespace name to all functions and variables inside the namespace code (it should be noted that C style macros are not included in the namespace and should be used with care because C macros are a preprocessor feature that does not contribute to the code's compiled syntax). To explain why we should namespace everything when creating our own libraries, we'll look at some examples.

Example 1

Example 1 demonstrates how to wrap your library's APIs in a C++ namespace :

// Contents of library.h

namespace library_name
{
int my_api() { return 42; }
// ...
}

// Contents of main.cpp

#include <iostream>

int main(void)
{
using namespace library_name;

std::cout << "The answer is: " << my_api() << '\n';
return 0;
}

As shown in the preceding example, the contents of the library are wrapped in a namespace and stored in the header (this example demonstrates a header-only library, which is an extremely useful design approach as the end user doesn't have to compile libraries, install them on his/her system, and then link against them). The library user simply includes the library header file and uses the using namespace library_name statement to unwrap the library's APIs. If the user has more than one library with the same API names, this statement can be omitted to remove any ambiguity. 

Example 2

Example 2 expands upon the previous example and demonstrates how to wrap your library's APIs in a C++ namespace header-only library while still including global variables:

// Contents of library.h

namespace library_name
{
namespace details { inline int answer = 42; }

int my_api() { return details::answer; }
// ...
}

// Contents of main.cpp

#include <iostream>

int main(void)
{
using namespace library_name;

std::cout << "The answer is: " << my_api() << '\n';
return 0;
}

As shown in the preceding example, C++17 was leveraged to create an inline global variable that is wrapped in our library's namespace. inline variables are needed as header-only libraries don't have a source file to define global variables; without the inline keyword, defining a global variable in a header would result in the variable being defined multiple times (that is, the result would be a linking error during compilation). C++17 resolved this issue by adding inline global variables, which allows a header-only library to define global variables without the need for tricky magic (such as returning a pointer to a static variable from a singleton style function).

In addition to the library's namespace , we wrapped the global variable in a details namespace. This is done to create a private place within your library in case the user of the library declares using namespace library_name. If the user does this, all of the APIs and variables that are wrapped by the library_name namespace become globally accessible within the scope of the main() function. For this reason, any private APIs or variables that are not meant to be accessible by the user should be wrapped by a second namespace (typically called details) to prevent their global accessibility. Finally, leveraging C++17's inline keyword allows us to create a global variable for use in our library while still supporting a header-only design. 

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime
Visually different images