1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
#include <utility>
#include <concepts>
//comparable
template <typename Type>
concept Comparable =
requires (Type lhs, Type rhs)
{
lhs == rhs;
lhs != rhs;
};
template <typename Type>
concept Incrementable =
requires (Type type)
{
++type;
type++;
};
//=
//dereference
template <typename Type>
concept Dereferenceable =
requires(Type type)
{
{ *type } -> std::same_as<typename Type::value_type &>;
};
//=
//constderef
template <typename Type>
concept ConstDereferenceable =
requires(Type const &type)
{
{ *type } -> std::same_as<typename Type::value_type const &>;
};
//=
struct InIt
{
typedef int value_type;
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 <typename Type>
concept InIterator =
Comparable<Type> and Incrementable<Type> and
ConstDereferenceable<Type>;
template <InIterator Type>
void inFun(Type tp)
{}
//=
struct OutIt: public InIt
{
int &operator*();
};
//outiterator
template <typename Type>
concept OutIterator =
Comparable<Type> and Incrementable<Type> and
Dereferenceable<Type>;
template <OutIterator Type>
void outFun(Type tp)
{}
//=
//fwditerator
template <typename Type>
concept FwdIterator =
InIterator<Type> and OutIterator<Type>;
struct FwdIt: public OutIt
{
using OutIt::operator*;
using InIt::operator*;
};
template <FwdIterator Type>
void fwdFun(Type tp)
{}
//=
//iterable
struct Iterable
{
typedef int value_type;
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 <typename Type>
concept BiIterator =
FwdIterator<Type> and
requires(Type type)
{
--type;
type--;
};
template <typename Type>
concept RndIterator =
BiIterator<Type>
and
requires(Type lhs, Type rhs)
{
lhs += 0;
lhs -= 0;
lhs + 0;
lhs - 0;
{ lhs - rhs } -> std::same_as<int>;
};
//=
struct BiIt: public FwdIt
{
InIt &operator--();
InIt operator--(int);
};
template <BiIterator Type>
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 <RndIterator Type>
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
}
|