Home Item 23 - Concepts(English)
Post
Cancel

Item 23 - Concepts(English)

Concepts

In C++20, concepts are a new syntactical tool used to constrain template parameters, enhancing the readability of template code and improving error messages. Concepts help developers catch errors at compile time and provide more specific error information. They define the conditions that template parameters must meet, such as type traits, method signatures, or other properties that can be checked at compile time. Concepts make template code more intuitive and easier to understand, and significantly reduce the verbosity of error messages when templates are misused.

C++ templates are powerful, but when there’s a mistake, the error messages can be long and hard to decipher, making it difficult to pinpoint the issue.

Simple Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
 template<typename T>
 T Add(T a, T b)
 {
     return a + b;
 }

 class Class1
 {
 public:
     Class1(int value)
     {
         this->value = value;
     }

     int value;
 };


 int main()
 {
     std::cout << Add(3, 5) << std::endl;
     std::cout << Add(3.3, 5.5) << std::endl;
     Class1 c1(3);
     Class1 c2(5);
     std::cout << Add(c1, c2) << std::endl;

     return 0;
 }

It is clear to an experienced programmer that Add(c1, c2) will fail because Class1 does not implement operator+. Even for such a simple error, the error message can be over 200 lines long.

Type Parameters

Concepts can be used to constrain type parameters in templates.

Let’s define a concept for integer types using std::is_integral_v. This concept returns true for all primitive integer types except for double and float.

1
2
template<typename T>
concept Integral = std::is_integral_v<T>;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <concepts>
#include <limits>

template<typename T>
concept Integral = std::is_integral_v<T>;

// Type Parameters
template<Integral T>
class IntegralNumericLimits {
public:
    static T min() { return std::numeric_limits<T>::min(); }
    static T max() { return std::numeric_limits<T>::max(); }
};

int main() {
    std::cout <<" IntegralNumericLimits<bool>::max() : " << IntegralNumericLimits<bool>::max() << std::endl;
    std::cout << " IntegralNumericLimits<int>::max() " << IntegralNumericLimits<int>::max() << std::endl;
    std::cout << " IntegralNumericLimits<unsigned int>::max() : " << IntegralNumericLimits<unsigned int>::max() << std::endl;
    std::cout << " std::numeric_limits<double>::max() : " << std::numeric_limits<double>::max() << std::endl;

    return 0;
}

Execution result:

Desktop View

When double is used:

1
std::cout << " IntegralNumericLimits::max() : " << IntegralNumericLimits<double>::max() << std::endl;

The error message is clear and concise!

Desktop View

Requires Expressions

Requires expressions can check specific conditions, such as whether a type has certain member functions or properties.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <concepts>

template<typename T>
concept Printable = requires(T t) {
    { std::cout << t };
};

class Printer {
public:
    void print(Printable auto value) {
        std::cout << "Printing: " << value << std::endl;
    }
};

int main() {
    Printer printer;
    printer.print(58);    // OK
    printer.print("Hello, World!"); // OK
    
    return 0;
}

Desktop View

Example with std::vector:

1
printer.print(std::vector<int>{1, 2, 3});

Compilation will fail because std::vector does not satisfy Printable.

Desktop View

Usage Scenarios

Concepts are suitable for the following scenarios:

  1. Improving Template Code Readability: Concepts make the requirements for template parameters explicit and the code easier to understand.
  2. Improving Error Messages: The compiler can check whether parameters meet the concepts at compile time, providing more specific error information instead of vague template errors.
  3. Strengthening Code Constraints: Concepts prevent inappropriate types from being used in templates, increasing code safety and stability.

Give concepts a try to enhance your template programming experience!

☝ツ☝

This post is licensed under CC BY 4.0 by the author.

👈 ツ 👍