src/functional.h

changeset 63
f7dd937667a5
child 106
128efb9d148b
equal deleted inserted replaced
62:3e92760fe00a 63:f7dd937667a5
1 /*
2 * LDForge: LDraw parts authoring CAD
3 * Copyright (C) 2020 Teemu Piippo
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #pragma once
20 #include <algorithm>
21 #include <functional>
22 #include <QVector>
23 #include <QSet>
24 #include <QList>
25
26 namespace fn
27 {
28 template<typename C>
29 class InsertIterator;
30 }
31
32 /**
33 * Like std::back_inserter but calls x.insert(v) instead
34 */
35 template<typename C>
36 class fn::InsertIterator
37 {
38 public:
39 InsertIterator(C& container) :
40 container{container} {}
41 auto operator*()
42 {
43 return *this;
44 }
45 auto operator++()
46 {
47 return *this;
48 }
49 auto operator++(int)
50 {
51 return *this;
52 }
53 template<typename T>
54 auto operator=(T&& value)
55 {
56 this->container.insert(std::forward<T>(value));
57 return *this;
58 }
59 private:
60 C& container;
61 };
62
63 namespace fn
64 {
65 // Constructs a fn::InsertIterator
66 template<typename C>
67 InsertIterator<C> makeInsertIterator(C& container)
68 {
69 return InsertIterator<C>{container};
70 }
71
72 // Constructs a back_inserter for std::vector
73 template<typename T>
74 auto makeDefaultInserter(std::vector<T>& vec)
75 {
76 return std::back_inserter(vec);
77 }
78
79 // Constructs a back_inserter for QVector
80 template<typename T>
81 auto makeDefaultInserter(QVector<T>& vec)
82 {
83 return std::back_inserter(vec);
84 }
85
86 // Constructs a back_inserter for QList
87 template<typename T>
88 auto makeDefaultInserter(QList<T>& vec)
89 {
90 return std::back_inserter(vec);
91 }
92
93 // Constructs an fn::InsertIterator for QSet
94 template<typename T>
95 auto makeDefaultInserter(QSet<T>& vec)
96 {
97 return InsertIterator(vec);
98 }
99
100 // Changes the value type of C
101 template<typename C, typename TT>
102 struct ChangeContainerValueType
103 {
104 };
105
106 // Changes the value type of std::vector
107 template<typename T, typename TT>
108 struct ChangeContainerValueType<std::vector<T>, TT>
109 {
110 using type = std::vector<TT>;
111 };
112
113 // Changes the value type of QVector
114 template<typename T, typename TT>
115 struct ChangeContainerValueType<QVector<T>, TT>
116 {
117 using type = QVector<TT>;
118 };
119
120 // Changes the value type of QSet
121 template<typename T, typename TT>
122 struct ChangeContainerValueType<QSet<T>, TT>
123 {
124 using type = QSet<TT>;
125 };
126
127 // Changes the value type of QList
128 template<typename T, typename TT>
129 struct ChangeContainerValueType<QList<T>, TT>
130 {
131 using type = QList<TT>;
132 };
133
134 // Changes the value type of C
135 template<typename C, typename TT>
136 using ChangeContainerValueType_t = typename ChangeContainerValueType<C, TT>::type;
137
138 /**
139 * \brief Applies \c function to all elements of \c container
140 * \param container Container to iterate
141 * \param function Function to apply
142 * \param Rt result type. If not provided, a suitable result type is deduced from inputs
143 * \returns mapped result container
144 */
145 template<typename Rt = void, typename C, typename Fn>
146 auto map(C&& container, Fn&& function)
147 {
148 using value_t = decltype(*std::declval<C>().begin());
149 using newvalue_t = std::result_of_t<Fn(value_t)>;
150 using result_t = std::conditional_t<
151 std::is_same_v<Rt, void>,
152 ChangeContainerValueType_t<std::remove_reference_t<C>, newvalue_t>,
153 Rt>;
154 result_t result;
155 result.reserve(std::end(container) - std::begin(container));
156 std::transform(std::begin(container), std::end(container), makeDefaultInserter(result), function);
157 return result;
158 }
159 }

mercurial