LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
SortByPointers.h
Go to the documentation of this file.
1 
10 #ifndef LARCOREALG_COREUTILS_SORTBYPOINTER_H
11 #define LARCOREALG_COREUTILS_SORTBYPOINTER_H
12 
13 // LArSoft libraries
14 #include "larcorealg/CoreUtils/MetaUtils.h" // util::is_unique_ptr_v<>
16 
17 // C/C++ standard libraries
18 #include <algorithm> // std::transform(), std::sort()
19 #include <iterator> // std::back_inserter()
20 #include <memory> // std::addressof()
21 #include <type_traits> // std::add_pointer_t
22 #include <utility> // std::move()
23 #include <vector>
24 
25 namespace util {
26 
27  namespace details {
28 
29  template <typename Coll, typename PtrColl>
31 
32  } // namespace details
33 
34  //----------------------------------------------------------------------------
41  template <typename Coll>
42  auto makePointerVector(Coll& coll);
43 
44  //----------------------------------------------------------------------------
57  template <typename Coll, typename PtrColl>
58  void MoveFromPointers(Coll& dest, PtrColl& src)
59  {
61  }
62 
63  //----------------------------------------------------------------------------
92  template <typename Coll, typename Sorter>
93  void SortByPointers(Coll& coll, Sorter sorter);
94 
95  //----------------------------------------------------------------------------
108  template <typename Coll, typename Sorter>
109  void SortUniquePointers(Coll& coll, Sorter&& sorter);
110 
111  //----------------------------------------------------------------------------
112 
113 } // namespace util
114 
115 //------------------------------------------------------------------------------
116 //--- Template implementation
117 //------------------------------------------------------------------------------
118 namespace util::details {
119 
120  //----------------------------------------------------------------------------
121  template <typename Coll, typename = void>
123 
124  static auto make(Coll& coll)
125  {
126 
127  using std::begin, std::end;
128 
129  using pointer_type = decltype(&*begin(coll));
130  using ptr_coll_t = std::vector<pointer_type>;
131 
132  auto const n = coll.size();
133 
134  //
135  // create the collection of pointers to data
136  //
137  ptr_coll_t ptrs;
138  ptrs.reserve(n);
139  std::transform(
140  begin(coll), end(coll), std::back_inserter(ptrs), [](auto& obj) { return &obj; });
141 
142  return ptrs;
143 
144  } // make()
145 
146  }; // struct PointerVectorMaker<>
147 
148  template <typename Coll>
149  struct PointerVectorMaker<Coll,
150  std::enable_if_t<util::is_unique_ptr_v<typename Coll::value_type>>> {
151 
152  static auto make(Coll& coll)
153  {
154 
155  using coll_t = Coll;
156  using unique_ptr_t = typename coll_t::value_type;
157  using value_type = typename unique_ptr_t::element_type;
158  using pointer_type = std::add_pointer_t<value_type>;
159  using ptr_coll_t = std::vector<pointer_type>;
160 
161  static_assert(util::is_unique_ptr_v<unique_ptr_t>); // kind of silly now
162 
163  using std::size;
164  auto const n = size(coll);
165 
166  //
167  // create the collection of pointers to data
168  //
169  ptr_coll_t ptrs;
170  ptrs.reserve(n);
171  std::transform(
172  coll.begin(), coll.end(), std::back_inserter(ptrs), [](auto& obj) { return obj.get(); });
173 
174  return ptrs;
175 
176  } // make()
177 
178  }; // struct PointerVectorMaker<unique_ptr>
179 
180  //----------------------------------------------------------------------------
181 
182 } // namespace util::details
183 
184 //------------------------------------------------------------------------------
185 template <typename Coll>
186 auto util::makePointerVector(Coll& coll)
187 {
189 }
190 
191 //------------------------------------------------------------------------------
192 template <typename Coll, typename Sorter>
193 void util::SortByPointers(Coll& coll, Sorter sorter)
194 {
195 
196  using coll_t = Coll;
197 
198  //
199  // create the collection of pointers to data
200  //
201  auto ptrs = makePointerVector(coll);
202 
203  //
204  // delegate the sorting by pointers
205  //
206  sorter(ptrs);
207 
208  //
209  // create a sorted collection moving the content from the original one
210  //
211  coll_t sorted;
212  MoveFromPointers(sorted, ptrs);
213 
214  //
215  // replace the old container with the new one
216  //
217  coll = std::move(sorted);
218 
219 } // util::SortByPointers()
220 
221 //------------------------------------------------------------------------------
222 template <typename Coll, typename Sorter>
223 void util::SortUniquePointers(Coll& coll, Sorter&& sorter)
224 {
225 
226  using Collection_t = Coll;
227  using UPtr_t = typename Collection_t::value_type;
228 
229  static_assert(util::is_unique_ptr_v<UPtr_t>);
230 
231  //
232  // create the collection of pointers to data
233  //
234  auto ptrs = makePointerVector(coll);
235 
236  // data pointer -> index
237  auto const ptrIndex = util::makeValueIndex(ptrs);
238 
239  //
240  // delegate the sorting by pointers
241  //
242  sorter(ptrs);
243 
244  //
245  // create a sorted collection moving the content from the original one
246  //
247  Collection_t sorted;
248  for (auto const& dataPtr : ptrs) {
249  std::size_t const originalIndex = ptrIndex.at(dataPtr);
250  sorted.emplace_back(std::move(coll[originalIndex]));
251  }
252 
253  //
254  // replace the old container with the new one
255  //
256  coll = std::move(sorted);
257 
258 } // util::SortUniquePointers()
259 
260 //------------------------------------------------------------------------------
261 namespace util {
262  namespace details {
263 
264  template <typename Coll, typename PtrColl>
265  void moveFromPointersImplBase(Coll& dest, PtrColl& src)
266  {
267  for (auto&& ptr : src)
268  dest.push_back(std::move(*ptr));
269  }
270 
271  template <typename Coll, typename PtrColl>
272  struct MoveFromPointersImpl {
273  static void move(Coll& dest, PtrColl& src)
274  {
275  dest.clear();
276  moveFromPointersImplBase(dest, src);
277  }
278  }; // struct MoveFromPointersImpl
279 
280  template <typename Data, typename PtrColl>
281  struct MoveFromPointersImpl<std::vector<Data>, PtrColl> {
282  static void move(std::vector<Data>& dest, PtrColl& src)
283  {
284  dest.clear();
285  dest.reserve(src.size());
286  moveFromPointersImplBase(dest, src);
287  }
288  }; // struct MoveFromPointersImpl
289 
290  } // namespace details
291 } // namespace util
292 
293 //------------------------------------------------------------------------------
294 
295 #endif // LARCOREALG_COREUTILS_SORTBYPOINTER_H
static void move(std::vector< Data > &dest, PtrColl &src)
static void move(Coll &dest, PtrColl &src)
Namespace for general, non-LArSoft-specific utilities.
Definition: PIDAAlg.h:26
Basic C++ metaprogramming utilities.
Provides util::makeValueIndex() helper function.
auto makePointerVector(Coll &coll)
Creates a STL vector with pointers to data from another collection.
STL namespace.
void SortUniquePointers(Coll &coll, Sorter &&sorter)
Sorts a vector of unique pointers using a C pointer sorter.
decltype(auto) constexpr end(T &&obj)
ADL-aware version of std::end.
Definition: StdUtils.h:77
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:101
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
void SortByPointers(Coll &coll, Sorter sorter)
Applies sorting indirectly, minimizing data copy.
void moveFromPointersImplBase(Coll &dest, PtrColl &src)
static auto make(Coll &coll)
void MoveFromPointers(Coll &dest, PtrColl &src)
Moves the content from a collection of pointers to one of data.
Char_t n[5]
decltype(auto) constexpr begin(T &&obj)
ADL-aware version of std::begin.
Definition: StdUtils.h:69
decltype(auto) makeValueIndex(Coll const &coll, Extractor getter)
Returns a map of value to index.