2 Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
7 * @file AthContainers/tools/DVL_algorithms.icc
8 * @author scott snyder <snyder@bnl.gov>
10 * @brief Helpers for STL algorithms for @c DataVector/List.
14 #include "AthContainers/tools/DVLNoBase.h"
15 #include "AthContainers/tools/DVLCast.h"
16 #include "AthContainers/AuxElement.h"
17 #include "AthContainersInterfaces/AuxStore_traits.h"
21 template <class DV> class ConstDataVector;
24 namespace DataModel_detail {
28 * @brief Comparison helper for @c DataVector/List classes.
30 * When doing operations such as @c sort on a @c DataVector/List,
31 * we'd like to be able to give to sort the iterators of the underlying
32 * @c BaseContainer container, for the sake of efficiency. But we also
33 * have to make sure that the comparisons see the proper pointer types
34 * for derived @c DataVector/List classes. This can be done with the following
35 * functional wrapper. This wraps a comparison object, putting the
36 * arguments through @c DVLCast before calling the comparison.
38 * There is also a specialization for the case where no casting
41 template <class DVL, class Compare, class DVL_Base=typename DVL::DVL_BASE>
44 typedef typename DVL::BaseContainer::value_type inptr;
46 Compwrapper (Compare comp) : m_comp (comp) {}
47 bool operator() (inptr x, inptr y)
49 return m_comp (DataModel_detail::DVLCast<DVL>::cast (x),
50 DataModel_detail::DVLCast<DVL>::cast (y));
56 * @brief Comparison helper for @c DataVector/List classes (specialization).
58 * This is specialized for the case where we're dealing with
59 * a base @c DataVector/List, and thus no casting is required.
61 template <class DVL, class Compare>
62 struct Compwrapper<DVL, Compare, DataModel_detail::NoBase>
65 Compwrapper (Compare comp) : Compare (comp) {}
70 * @brief Predicate helper for @c DataVector/List classes.
72 * When doing operations such as @c partition on a @c DataVector/List,
73 * we'd like to be able to give the operation the iterators of the underlying
74 * @c BaseContainer container, for the sake of efficiency. But we also
75 * have to make sure that the predicate sees the proper pointer types
76 * for derived @c DataVector/List classes. This can be done with the following
77 * functional wrapper. This wraps a predicate object, putting the
78 * arguments through @c DVLCast before calling the predicate.
80 * There is also a specialization for the case where no casting
83 template <class DVL, class Predicate, class DVL_Base=typename DVL::DVL_BASE>
86 typedef typename DVL::BaseContainer::value_type inptr;
88 Predwrapper (Predicate pred) : m_pred (pred) {}
89 bool operator() (inptr x)
91 return m_pred (DataModel_detail::DVLCast<DVL>::cast (x));
97 * @brief Predicate helper for @c DataVector/List classes (specialization).
99 * This is specialized for the case where we're dealing with
100 * a base @c DataVector/List, and thus no casting is required.
102 template <class DV, class Predicate>
103 struct Predwrapper<DV, Predicate, DataModel_detail::NoBase>
106 Predwrapper (Predicate pred) : Predicate (pred) {}
111 * @brief Specialization of @c remove for @c DataVector/List.
112 * @param beg The start iterator for the remove.
113 * @param end The end iterator for the remove.
114 * @param value The value to remove.
116 * @c beg and @c end should both be iterators from the same @c DataVector/List.
117 * This performs the remove in a way that doesn't run afoul of
118 * @c DataVector/List's object ownership rules.
120 template <class Iterator, class T>
122 dvl_remove (Iterator beg,
126 beg = std::find (beg, end, value);
132 for (; beg != end; ++beg) {
133 if (!(*beg == value)) {
134 std::iter_swap (res, beg);
145 * @brief Specialization of @c remove_if for @c DataVector/List.
146 * @param beg The start iterator for the remove.
147 * @param end The end iterator for the remove.
148 * @param pred The predicate for the removal.
150 * @c beg and @c end should both be iterators from the same @c DataVector/List.
151 * This performs the remove in a way that doesn't run afoul
152 * of @c DataVector/List's object ownership rules.
154 template <class Iterator, class Predicate>
156 dvl_remove_if (Iterator beg,
160 beg = std::find_if (beg, end, pred);
166 for (; beg != end; ++beg) {
167 if (!bool(pred(*beg))) {
168 std::iter_swap (res, beg);
179 * @brief Specialization of @c unique for @c DataVector/List.
180 * @param beg The start iterator for the unique operation.
181 * @param end The end iterator for the unique operation.
183 * @c beg and @c end should both be iterators from the same @c DataVector/List.
184 * This performs the operation in a way
185 * that doesn't run afoul of @c DataVector/List's object ownership rules.
187 template <class Iterator>
189 dvl_unique (Iterator beg,
192 beg = std::adjacent_find (beg, end);
198 while (++beg != end) {
200 std::iter_swap (++res, beg);
209 * @brief Specialization of @c unique for @c DataVector/List.
210 * @param beg The start iterator for the unique operation.
211 * @param end The end iterator for the unique operation.
212 * @param pred The predicate for the operation.
214 * @c beg and @c end should both be iterators from the same @c DataVector/List.
215 * This performs the operation in a way
216 * that doesn't run afoul of @c DataVector/List's
217 * object ownership rules.
219 template <class Iterator, class BinaryPredicate>
221 dvl_unique (Iterator beg,
223 BinaryPredicate pred)
225 beg = std::adjacent_find (beg, end, pred);
231 while (++beg != end) {
232 if (!pred(*res, *beg))
233 std::iter_swap (++res, beg);
242 * @brief Reset indices / reorder aux data after elements have been permuted.
243 * @param beg Start of the range of elements to process.
244 * @param end End of the range of elements to process.
246 * Call this after some operation that has permuted the elements in the
247 * container (such as sort). The index information in the elements
248 * will be used to permute all auxiliary data in the same way.
249 * Finally, all the indices will be reset in the correct order.
251 * @c ForwardIterator should be an iterator over the @c DataVector
252 * (not a base iterator).
254 template <class ForwardIterator>
256 void resortAux (ForwardIterator beg,
259 // Forward to the appropriate specialization, depending on whether
260 // or not aux data is supported.
261 typedef typename std::iterator_traits<ForwardIterator>::value_type valtype;
262 resortAux1 (typename SG::AuxStore_traits<valtype>::flag(), beg, end);
267 * @brief Reset indices / reorder aux data after elements have been permuted.
268 * @param beg Start of the range of elements to process.
269 * @param end End of the range of elements to process.
274 void resortAux1 (const std::true_type&,
275 typename DataModel_detail::iterator<DVL> beg,
276 typename DataModel_detail::iterator<DVL> end)
279 DVL* cont = dynamic_cast<DVL*> (beg.container());
281 cont->resortAux (beg, end);
287 * @brief Reset indices / reorder aux data after elements have been permuted.
288 * @param beg Start of the range of elements to process.
289 * @param end End of the range of elements to process.
291 * Aux data case with reverse iterators.
294 void resortAux1 (const std::true_type&,
295 typename std::reverse_iterator<typename DataModel_detail::iterator<DVL> > beg,
296 typename std::reverse_iterator<typename DataModel_detail::iterator<DVL> > end)
299 DVL* cont = dynamic_cast<DVL*> (beg.base().container());
301 cont->resortAux (end.base(), beg.base());
307 * @brief Reset indices / reorder aux data after elements have been permuted.
308 * @param beg Start of the range of elements to process.
309 * @param end End of the range of elements to process.
311 * No-auxdata case; just a no-op.
313 template <class ForwardIterator>
315 void resortAux1 (const std::false_type&,
322 } // namespace DataModel_detail