Concepts (C++20) define named sets of template requirements.
Class templates, function templates, and non-template functions (typically members of class templates) may be
associated with a template constraint, which specifies the requirements on template arguments, which can be used
to select the most appropriate function overloads and template specializations.
Each concept is a predicate, evaluated at compile time, and becomes a part of the interface of a template where
it is used as a constraint:
template<typenameT>conceptNumber=std::is_arithmetic_v<T>;// is_arithmetic_v might be misleading since it also includes bool// is_arithmetic_v might be misleading since it doesn't include std::complex
// These expressions must be something that will compiletemplate<typenameT>conceptRange=requires(Tr){*r.begin();*r.end();};
1234
// These expressions must something that will compiletemplate<typenameT>conceptHasValueType=requires(Tr){typenameT::value_type;// required nested name};
12345
// Two requirements at the same timetemplate<typenameT>conceptPair=requires(Tp){{p.first};{p.second};};
123456
// The expression should not only compile, but it should also have// a type that passes the concept after ->template<typenameT>conceptIntPair=requires(Tp){{p.first}->std::same_as<int>;{p.second}->std::same_as<int>;};
// Additional constraint to existing constraints// Functions can use Range or RangeSameType now without ambiguitytemplate<typenameT>conceptPairSameType=Pair<T>&&requires(Tp){{p.first}->std::same_as<decltype(p.second)>;};
// Number, but nor SignedNumber neither UnsignedNumbertemplate<NumberT>voidmax_value(Ta,Tb){if(a>b){std::cout<<"max_value: "<<a<<'\n';}else{std::cout<<"max_value: "<<b<<'\n';}}
1 2 3 4 5 6 7 8 91011121314151617
// This function is used when Number is SignedNumbertemplate<SignedNumberT>voidmax_value(Ta,Tb){if(a>b){if(a>0){std::cout<<"max_value: positive "<<a<<'\n';}else{std::cout<<"max_value: negative "<<-a<<'\n';}}else{if(b>0){std::cout<<"max_value: positive "<<b<<'\n';}else{std::cout<<"max_value: negative "<<-b<<'\n';}}}
123456789
// This function is used when Number is UnsignedNumbertemplate<UnsignedNumberT>voidmax_value(Ta,Tb){if(a>b){std::cout<<"max_value: +"<<a<<'\n';}else{std::cout<<"max_value: +"<<b<<'\n';}}
// - The most constrained concept is always usedtemplate<RangeT>voidprint_element(constT&c){for(constauto&item:c){std::cout<<item<<' ';}std::cout<<'\n';}
123456789
// The most constrained concept is used in nested constraintstemplate<RangeWithValueTypeT>voidprint_element(constT&c){std::cout<<typeid(typenameT::value_type).name()<<": ";for(constauto&item:c){std::cout<<item<<' ';}std::cout<<'\n';}
123456789
template<typenameT>requiresEqualityComparable<T>voidcompare(constT&a,constT&b){if(a==b){std::cout<<a<<" == "<<b<<" is "<<(a==b?"true":"false")<<'\n';}else{std::cout<<a<<" != "<<b<<" is "<<(a!=b?"true":"false")<<'\n';}}