#include #include //comparable template concept Comparable = requires (Type lhs, Type rhs) { lhs == rhs; lhs != rhs; }; template concept Incrementable = requires (Type type) { ++type; type++; }; //= //dereference template concept Dereferenceable = requires(Type type) { { *type } -> std::same_as; }; //= //constderef template concept ConstDereferenceable = requires(Type const &type) { { *type } -> std::same_as; }; //= struct InIt { using value_type = int; InIt &operator++(); InIt operator++(int); int const &operator*() const; }; bool operator==(InIt const &lh, InIt const &rh); bool operator!=(InIt const &lh, InIt const &rh); int operator-(InIt const &lh, InIt const &rh); //initerator template concept InIterator = Comparable and Incrementable and ConstDereferenceable; template void inFun(Type tp) {} //= struct OutIt: public InIt { int &operator*(); }; //outiterator template concept OutIterator = Comparable and Incrementable and Dereferenceable; template void outFun(Type tp) {} //= //fwditerator template concept FwdIterator = InIterator and OutIterator; struct FwdIt: public OutIt { using OutIt::operator*; using InIt::operator*; }; template void fwdFun(Type tp) {} //= //iterable struct Iterable { using value_type = int; Iterable &operator++(); Iterable operator++(int); int const &operator*() const; int &operator*(); }; bool operator==(Iterable const &lh, Iterable const &rh); bool operator!=(Iterable const &lh, Iterable const &rh); int operator-(Iterable const &lh, Iterable const &rh); //= //bidir template concept BiIterator = FwdIterator and requires(Type type) { --type; type--; }; template concept RndIterator = BiIterator and requires(Type lhs, Type rhs) { lhs += 0; lhs -= 0; lhs + 0; lhs - 0; { lhs - rhs } -> std::same_as; }; //= struct BiIt: public FwdIt { InIt &operator--(); InIt operator--(int); }; template void biFun(Type tp) {} //randomit struct RndIt: public BiIt { RndIt &operator+=(int); RndIt &operator-=(int); }; RndIt &operator+(RndIt const &lh, int); RndIt &operator-(RndIt const &lh, int); template void rndFun(Type tp) {} int main() { inFun(InIt{}); // outFun(InIt{}); // WC: unsatisfied constraint outFun(OutIt{}); // fwdFun(OutIt{}); // WC fwdFun(FwdIt{}); inFun(Iterable{}); outFun(Iterable{}); fwdFun(Iterable{}); biFun(BiIt{}); // biFun(InIt{}); // WC // biFun(OutIt{}); // WC rndFun(RndIt{}); biFun(RndIt{}); // OK: extra functions are fine }