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
Explore 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
C++ System Programming Cookbook

You're reading from   C++ System Programming Cookbook Practical recipes for Linux system-level programming using the latest C++ features

Arrow left icon
Product type Paperback
Published in Feb 2020
Publisher Packt
ISBN-13 9781838646554
Length 292 pages
Edition 1st Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Onorato Vaticone Onorato Vaticone
Author Profile Icon Onorato Vaticone
Onorato Vaticone
Arrow right icon
View More author details
Toc

Table of Contents (13) Chapters Close

Preface 1. Getting Started with System Programming 2. Revisiting C++ FREE CHAPTER 3. Dealing with Processes and Threads 4. Deep Dive into Memory Management 5. Using Mutexes, Semaphores, and Condition Variables 6. Pipes, First-In First-Out (FIFO), Message Queues, and Shared Memory 7. Network Programming 8. Dealing with Console I/O and Files 9. Dealing with Time Interfaces 10. Managing Signals 11. Scheduling 12. Other Books You May Enjoy

Understanding concepts

A concept is a compile-time predicate that's used in conjunction with templates. The C++20 standard definitely boosted generic programming by providing more compile-time opportunity for the developer to communicate its intention. We can visualize concepts such as requirements (or constraints) the user of the template must adhere to. Why do we need concepts? Do you have do define concepts by yourself? This recipe will answer these and many more questions.

How to do it...

In this section, we will develop a concrete template example using concepts:

  1. We want to create our own version of the std::sort template function from the C++ standard library. Let's start by writing the following code in a .cpp file:
#include <algorithm>
#include <concepts>

namespace sp
{
template<typename T>
requires Sortable<T>
void sort(T& container)
{
std::sort (begin(container), end(container));
};
}
  1. Now, let's use our new template class with the constraint that the type we pass, an std::vector, must be sortable; otherwise, the compiler will notify us:
int main()
{
std::vector<int> myVec {2,1,4,3};
sp::sort(vec);

return 0;
}

We'll look at the details in the next section.

How it works...

I strongly believe concepts were the missing feature. Before them, a template didn't have a well-defined set of requirements, nor, in the case of a compilation error, a simple and brief description of it. These are the two pillars that drove the design of the concepts feature.

Step 1 includes the algorithms include for the std::sort method and the concepts header. To not confuse the compiler and ourselves, we encapsulated our new template in a namespace, sp. As you can see, there is a very minimal difference compared to the classical templates we used to use and the difference is with the requires keyword.

requires communicates to the compiler (and to the template user) that this template is only valid with a T Sortable type (Sortable<T>). OK; what is Sortable? This is a predicate that is only satisfied if it is evaluated to true. There are other ways to specify a constraint, as follows:

  • With the trailing requires:
template<typename T>
void sort(T& container) requires Sortable<T>;
  • As a template parameter:
template<Sortable T>
void sort(T& container)

I personally prefer the style in the How to do it... section as it is more idiomatic and, more importantly, allows us to keep all the requires together, like so:

template<typename T>
requires Sortable<T> && Integral<T>
void sort(T& container)
{
std::sort (begin(container), end(container));
};

In this example, we want to communicate that our sp::sort method is valid with type T, which is Sortable and Integral, for whatever reason.

Step 2 simply uses our new customized version of sort. To do this, we instantiated a vector (which is Sortable!) and passed in input to the sp::sort method.

There's more...

There might be cases where you need to create your own concept. The standard library contains plenty of them, so it is a remote probability that you'd need one. As we learned in the previous section, a concept is a predicate if and only if it is evaluated as true. The definition of a concept as a composite of two existing ones might look like this:

template <typename T>
concept bool SignedSwappable() 
{ return SignedIntegral<T>() && Swappable<T>(); }

Here, we can use the sort method:

template<typename T>
requires SignedSwappable<T>
void sort(T& container)
{
std::sort (begin(container), end(container));
};

Why is this cool? For a couple of reasons:

  • It lets us immediately know what the template expects without getting lost in implementation details (that is, the requirements or constraints are explicit).
  • At compile time, the compiler will evaluate whether the constraints have been met.

See also

You have been reading a chapter from
C++ System Programming Cookbook
Published in: Feb 2020
Publisher: Packt
ISBN-13: 9781838646554
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 $19.99/month. Cancel anytime