C++20 Concepts: part 3
In this article we’ll dive deeper in the details of concepts and build upon the topics already explained in the first and second part.
1. Introduction
In the second part of the tutorial series, the idea behind the concepts imposing semantic restrictions on generic code was explained and the three ways of defining and using concepts were discussed. In this article, I’ll take a step further into writing the definitions of concepts.
2. Concepts with multiple semantic restrictions
Imagine a scenario where generic functions/methods have to be written whereby each function performs one mathematical operation (one of add, subtract, divide, multiply) on two input parameter and prints the result on the console. Lets call them sumAndPrint
, subtractAndPrint
, multiplyAndPrint
anddivideAndPrint
respecitvely.
The sumAndPrint
generic function could look like below:
template <typename T>
void sumAndPrint(const T num1, const T num2)
{
std::cout << (num1 + num2);
}
Similarly one could define the remaining three generic functions that can perform the remaining math operations viz -
, *
, \
and print the result on console. So how can one write a concept
and ensure the template parameter follows the semantics of math operations and is as well streamable ?
One just needs to define a concept with multiple rules within the body:
template <typename T>
concept ConceptName = requires(T param1, T param2, ... )
{
{/* rule 1 */};
{/* rule 2*/ };
.
.
.};
Coming back to our concept for the four generic methods, lets name it IsArithmeticOpAPrintable
, can be defined as follows:
template <typename T>
concept IsArithmeticOpAPrintable = requires(T param1, T param2)
{
{std::cout << (num1 + num2)};
{std::cout << (num1 - num2)};
{std::cout << (num1 * num2)};
{std::cout << (num1 / num2)};
};
The body of the concept above imposes the semantic restrictions on the result of the mathematical operation performed with param1
and param2
, i.e param1 op param2
and says nothing about the parameters themselves!