Mircea Baja - 22 May 2020
int data[] = {2, 5, 7, 1, 22};int * it = find(std::begin(data), std::end(data), 5);if (it == std::end(data)) { // not found ...}else { // found ... *it = 42;}
int * find(int * f, int * l, int x) { while ((f != l) && (*f != x)) ++f; return f;}
find
and outside!=
, the other time with ==
template<typename It, typename T>It find(It f, It l, const T & x) { while ((f != l) && (*f != x)) ++f; return f;}
T
being int
, short
, long
, unsigned
etc.It
(for f
and l
) is pointer-like/position to sequences of
integer-like values (e.g. T *
)It
can also be an iterator in a linked list (dereferencing gives
value, not node; advance follows next
)T
and It
are integer-like not in the addition/multiplication sense, but
in the it holds a value that can be copied, compared for equality etc.f
and l
f
f
is reference to the value typef
(with ++
)f
equals l
, it stays that way, we can compare again and get the same
resultf
l
from f
, l
should not be dereferencedtemplate<typename It>using ValueType = typename It::value_type;template<typename It>concept InputIterator = requires(It a, It b){ {a == b} -> std::boolean; {a != b} -> std::boolean; typename ValueType<It>; {*a} -> std::common_reference_with<ValueType<It>>; ++a;};template<typename It> requires InputIterator<It>It find(It f, It l, const ValueType<It> & x){ while ((f != l) && (*f != x)) ++f; return f;}
template<InputIterator It, Sentinel<It> S, class T, class Proj = ranges::identity > requires IndirectRelation<ranges::equal_to<>, projected<It, Proj>, const T*>It find(It f, S l, const T& x, Proj proj = Proj{}){ while ((f != l) && (ranges::invoke(proj, *f) != x)) ++f; return f;}
T
is not necessarily the value type of the iteratorrange
e.g. the whole containerstd::cout << find(people, "Alice", &person::first_name)->last_name;
template<typename It, typename T>// requires It is an ForwardIterator// T is equality comparable with ValueType<It>,// T is assignable to ValueType<It>It find_by_setting_sentinel(It f, It l, const T & x) { // precondition: l can be dereferenced to store value as sentinel *l = x; while (*f != x) ++f; return f;}
template<typename It, typename Pred> // requires It is an ForwardIterator, // Pred is an unary predicate on ValueType(It) It partition_semistable(It f, It l, Pred pred) { f = std::find_if(f, l, pred); if (f == l) return f; for (It i = std::next(f); i != l; ++i) { if(!pred(*i)) { std::iter_swap(f, i); ++f; } } return f; }
accumulate
and reduce
with
regards to the associativity of the operation)for/while
loop is sometimes suitable, also more adaptable to changes
area of codestd::begin
Some a;a = b;assert(a == b);c = b;assert(a == c);
std::list
(also what state?)std::list
==
not !=
==
is different from not !=
push_back()
won't throw: vector
was previously resizedint min_int(int a, int b) { ... }float min_float(float a, float b) { ... }const std::vector<int> & min_vector_int( const std::vector<int> & a, const std::vector<int> & b) { ... }
int min_int(int a, int b) { ... }float min_float(float a, float b) { ... }const std::vector<int> & min_vector_int( const std::vector<int> & a, const std::vector<int> & b) { ... }
template<typename T>const T & min(const T & a, const T & b) { // implementation here}
int min_int(int a, int b) { ... }float min_float(float a, float b) { ... }const std::vector<int> & min_vector_int( const std::vector<int> & a, const std::vector<int> & b) { ... }
template<typename T>const T & min(const T & a, const T & b) { // implementation here}
if (a < b) return a; else return b; // 1if (a <= b) return a; else return b; // 2if (a > b) return b; else return a; // 3if (b < a) return b; else return a; // 4
template<typename T>concept EqualityComparable = requires (const T a, const T b) { { a == b } -> std::boolean; { a != b } -> std::boolean; };
template<typename T>concept StrictlyTotallyOrdered = EqualityComparable<T> && requires (const T a, const T b) { { a < b } -> std::boolean; { a > b } -> std::boolean; { a <= b } -> std::boolean; { a >= b } -> std::boolean;};
requires(T a, U b) { a + b; // simple: expression can compile typename T::sub_type; // type requirement { a + 1 } -> std::same_as<int>; // compile AND std::same_as<decltype(a+1), int>}
// requires clausetemplate<typename T> requires StrictlyTotallyOrdered<T>const T & min(const T & a, const T & b) { if (b < a) return b; else return a;}
template<StrictlyTotallyOrdered T>const T & min(const T & a, const T & b) { if (b < a) return b; else return a;}
// abbreviated function templateconst StrictlyTotallyOrdered auto & min( const StrictTotallyOrdered auto & a, const StrictTotallyOrdered auto & b) { if (b < a) return b; else return a;}
requires(T a, U b) { { a + 1 } -> std::same_as<int>; { a == b } -> std::boolean}
requires(T a, U b) { { a + 1 } -> std::same_as<int>; { a == b } -> std::boolean}
void fn(std::same_as<int> x); // inventfn(a + 1); // check if it compiles
requires(T a, U b) { { a + 1 } -> std::same_as<int>; { a == b } -> std::boolean}
void fn(std::same_as<int> x); // inventfn(a + 1); // check if it compiles
template<std::same_as<int> T>void fn(T x);
requires(T a, U b) { { a + 1 } -> std::same_as<int>; { a == b } -> std::boolean}
void fn(std::same_as<int> x); // inventfn(a + 1); // check if it compiles
template<std::same_as<int> T>void fn(T x);
template<typename T> requires std::same_as<T, int>void fn(T x);
template<InputIterator It, Sentinel<It> S, class T, class Proj = ranges::identity > requires IndirectRelation<ranges::equal_to<>, projected<It, Proj>, const T*>It find(It f, S l, const T& x, Proj proj = Proj{}){ while ((f != l) && (ranges::invoke(proj, *f) != x)) ++f; return f;}
Keyboard shortcuts
↑, ←, Pg Up, k | Go to previous slide |
↓, →, Pg Dn, Space, j | Go to next slide |
Home | Go to first slide |
End | Go to last slide |
Number + Return | Go to specific slide |
b / m / f | Toggle blackout / mirrored / fullscreen mode |
c | Clone slideshow |
p | Toggle presenter mode |
t | Restart the presentation timer |
?, h | Toggle this help |
Esc | Back to slideshow |