#include <iostream> #include <type_traits> // unconstrained template function auto show(auto x) { std::cout << x << '\n'; } // named requirement template <typename T> concept Number = std::is_integral_v<T> || std::is_floating_point_v<T>; // constrained template template <typename T> requires Number<T> auto show(T x) { std::cout << "number " << x << '\n'; } // trailing syntax /* template <typename T> auto show(T x) requires Number<T> { std::cout << "number " << x << '\n'; } // Shorthand syntax template <Number T> auto show(T x) { std::cout << "number " << x << '\n'; } */ // terse syntax Number auto add(Number auto x, Number auto y) { return x+y; } int main() { show(1); show("abc"); Number auto x = add(1, 2); // ok Number auto y = add(1, 3.14); // ok // Number auto z = add(1, "3"); // error: char* is not a Number }