Search⌘ K

How to Choose Among the Four Ways?

Understand the four main methods to apply C++20 concepts in functions, including requires clauses and abbreviated templates. Discover when to use each approach based on complexity and parameter needs, helping you write clearer, safer generic code.

We'll cover the following...

We’ve just seen four ways to use concepts. Let’s have a look at them together:

  • The requires clause
  • The trailing requires clause
  • The constrained template parameter
  • The abbreviated function templates
C++
#include <concepts>
#include <iostream>
//creating a concept 'Number'
template <typename T>
concept Number = std::integral<T> || std::floating_point<T>;
//using requires clause
template <typename T>
requires Number<T>
auto addRequiresClause(T a, T b) {
return a+b;
}
//using trailing requires clause
template <typename T>
auto addTrailingRequiresClause(T a, T b) requires Number<T> {
return a+b;
}
//using constrained template parameter
template <Number T>
auto addConstrainedTemplate(T a, T b) {
return a+b;
}
//using abbreviated function templates
auto addAbbreviatedFunctionTemplate(Number auto a, Number auto b) {
return a+b;
}
int main() {
std::cout << "addRequiresClause(1, 2): " << addRequiresClause(1, 2) << '\n';
// std::cout << "addRequiresClause(1, 2.5): "
// << addRequiresClause(1, 2.5) << '\n';
// error: no matching function for call to 'addRequiresClause(int, double)'
std::cout << "addTrailingRequiresClause(1, 2): "
<< addTrailingRequiresClause(1, 2) << '\n';
// std::cout << "addTrailinRequiresClause(1, 2): "
// << addTrailinRequiresClause(1, 2.5) << '\n';
// error: no matching function for call to
// 'addTrailinRequiresClause(int, double)'
std::cout << "addConstrainedTemplate(1, 2): "
<< addConstrainedTemplate(1, 2) << '\n';
// std::cout << "addConstrainedTemplate(1, 2): "
// << addConstrainedTemplate(1, 2.5) << '\n';
// error: no matching function for call to 'addConstrainedTemplate(int, double)'
std::cout << "addAbbreviatedFunctionTemplate(1, 2): "
<< addAbbreviatedFunctionTemplate(1, 2) << '\n';
std::cout << "addAbbreviatedFunctionTemplate(1, 2): "
<< addAbbreviatedFunctionTemplate(1, 2.14) << '\n';
}

Which method should we use? As always, it depends on what we’re working on. If we have a complex requirement, to be able to use an expression we need either the requires clause or the trailing ...