template concept bool Constraint() // function concept { return requires(Type lhs, Type rhs) { { lhs < rhs } -> bool; // multiple lhs + rhs; // constraints // typename Type::value_type; }; } template concept bool Constraint2 = // variable concept requires(Type lhs, Type rhs) { // { operator<(lhs, rhs) } -> bool; // both OK { lhs < rhs } -> bool; lhs + rhs; typename Type::value_type; }; // template concept bool Constraint = true ; struct Combi { using value_type = int; }; bool operator<(Combi const &lhs, Combi const &rhs); Combi operator+(Combi const &lhs, Combi const &rhs); template struct Data { void process(); }; template // Constraint must be specified, void Data::process() // but the formal type name { // doesn't have to be Type int x = 0; int y = x; x = y << 1; } template struct Data2 { void process(); }; template // Constraint must be specified, void Data2::process() // but the formal type name { // doesn't have to be Type int x = 0; int y = x; x = y << 1; } template requires Constraint2 struct Data3 { void process(); void another(); }; template // Constraint must be specified, void Data3::process() // but the formal type name {} // doesn't have to be Type template // Still constraint, due to Data3's void Data3::another() // constraints {} // Not OK: must be variable concept: // // template requires Constraint // struct Data4 // { // void process(); // }; // // template // Constraint must be specified, // void Data4::process() // but the formal type name // { // doesn't have to be Type // int x = 0; // int y = x; // x = y << 1; // } int main() { Data{}.process(); Data2{}.process(); }