Concepts (C++20)
A mechanism to place constraints on your template type parameters. An alternative to static asserts and type traits. This is a great feature to enforce rules on the users of your templates.
#include <iostream>
#include <type_traits>
template <typename T> void print_number(T n) {
static_assert(std::is_integral<T>::value, "Must pass an integral argument");
std::cout << "n : " << n << std::endl;
}
int main() {
print_number(5);
// print_number(55.2); will fail to compile
}
In C++, there are standard built in concepts, but we can also create our own ones.
Some built in concepts:
- same_as
- derived_from
- convertible_to
- common_reference_with
- common_with
- integral
- signed_integral
- unsigned_integral
- floating_point
Syntax for using concepts:
#include <concepts>
template <typename T>
requires std::integral<T>
T add(T a, T b) {
return a + b;
}
int main() {
add(4, 8);
// add(4.5, 8.6); error: constraint not satisfied
}
You can also use type traits:
template <typename T>
requires std::is_integral_v<T>
T add(T a, T b) {
return a + b;
}
You can also specify your concept directly:
template <std::integral T> T add(T a, T b) { return a + b; }
Using auto:
auto add(std::integral auto a, std::integral auto b) { return a + b; }
There are many syntax possibilities, some works better depending on the situation.
template <typename T>
T add(T a, T b) requires std::is_integral_v<T> {
return a + b;
}