1/*
2 * LegacyClonk
3 *
4 * Copyright (c) 2020, The LegacyClonk Team and contributors
5 *
6 * Distributed under the terms of the ISC license; see accompanying file
7 * "COPYING" for details.
8 *
9 * "Clonk" is a registered trademark of Matthes Bender, used with permission.
10 * See accompanying file "TRADEMARK" for details.
11 *
12 * To redistribute this file separately, substitute the full license texts
13 * for the above references.
14 */
15
16#pragma once
17
18#include <functional>
19#include <type_traits>
20
21// Provides all standard variants of begin and end
22// The iterable member must be designated by publicly using Iterable = [Const]IterableMember<&Class::Member>; in the class
23
24template<class Class>
25struct C4DelegatedIterable
26{
27 auto begin()
28 {
29 return std::invoke(Class::Iterable::Iterable, static_cast<Class *>(this)).begin();
30 }
31
32 auto end()
33 {
34 return std::invoke(Class::Iterable::Iterable, static_cast<Class *>(this)).end();
35 }
36
37 auto cbegin() const
38 {
39 return std::invoke(Class::Iterable::Iterable, static_cast<const Class *>(this)).cbegin();
40 }
41
42 auto cend() const
43 {
44 return std::invoke(Class::Iterable::Iterable, static_cast<const Class *>(this)).cend();
45 }
46
47 auto begin() const
48 {
49 return cbegin();
50 }
51
52 auto end() const
53 {
54 return cend();
55 }
56
57 auto rbegin()
58 {
59 return std::invoke(Class::Iterable::Iterable, static_cast<Class *>(this)).rbegin();
60 }
61
62 auto rend()
63 {
64 return std::invoke(Class::Iterable::Iterable, static_cast<Class *>(this)).rend();
65 }
66
67 auto crbegin() const
68 {
69 return std::invoke(Class::Iterable::Iterable, static_cast<const Class *>(this)).crbegin();
70 }
71
72 auto crend() const
73 {
74 return std::invoke(Class::Iterable::Iterable, static_cast<const Class *>(this)).crend();
75 }
76
77 auto rbegin() const
78 {
79 return crbegin();
80 }
81
82 auto rend() const
83 {
84 return crend();
85 }
86
87protected:
88 template<auto member>
89 class IterableMember
90 {
91 static constexpr auto Iterable = member;
92 friend C4DelegatedIterable<Class>;
93 };
94
95 template<auto member>
96 class ConstIterableMember
97 {
98 using Member = std::decay_t<std::invoke_result_t<decltype(member), Class>>;
99 static constexpr const Member Class:: *Iterable = member;
100 friend C4DelegatedIterable<Class>;
101 };
102};
103