All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
makeValueIndex.h
Go to the documentation of this file.
1 /**
2  * @file larcorealg/CoreUtils/makeValueIndex.h
3  * @brief Provides `util::makeValueIndex()` helper function.
4  * @author Gianluca Petrillo (petrillo@slac.stanford.edu)
5  * @date April 24, 2019
6  *
7  * This is a header-only library.
8  *
9  * This utility belongs to the same cetegory as `util::MakeIndex()`, but that
10  * one is definded in `lardataalg` and we need this one for geometry.
11  */
12 
13 #ifndef LARCOREALG_COREUTILS_MAKEVALUEINDEX_H
14 #define LARCOREALG_COREUTILS_MAKEVALUEINDEX_H
15 
16 
17 // LArSoft libraries
19 #include "larcorealg/CoreUtils/fromFutureImport.h" // util::pre_std::identity<>
21 
22 // C/C++ standard library
23 #include <map>
24 #include <stdexcept> // std::runtime_error
25 #include <string> // std::to_string()
26 #include <type_traits> // std::invoke_result_t, std::remove_reference_t
27 #include <cstddef> // std::size_t
28 
29 
30 namespace util {
31 
32  /**
33  * @brief Returns a map of value to index.
34  * @tparam Coll type of container
35  * @tparam Extractor type of value extraction function
36  * @param coll container to get the map of
37  * @param getter function applied to each element to extract the value for map
38  * @return a value-to-index associative container
39  * @throw std::runtime_error if multiple elements yield the same value
40  *
41  * The collection `coll` is navigated in sequence from `begin()` to `end()`,
42  * and a map is created where to each key, `getter(coll[i])`, the index `i`
43  * is associated. The value returned by `getter()` is copied into the key.
44  * Therefore that value needs to satisfy all the requirements of the key of
45  * the STL associative container `std::map`.
46  * Duplicate values will trigger an exception.
47  *
48  * Requirements
49  * -------------
50  *
51  * The collection type `Coll` must have:
52  * * `value_type` type defining the content of the container
53  * * support `begin()` and `end()` free functions returning input iterators,
54  * that is support a ranged-for loop
55  *
56  */
57  template <typename Coll, typename Extractor>
58  decltype(auto) makeValueIndex(Coll const& coll, Extractor getter);
59 
60  template <typename Coll>
61  auto makeValueIndex(Coll const& coll)
62  { return makeValueIndex(coll, util::pre_std::identity()); }
63 
64 } // namespace util
65 
66 
67 //------------------------------------------------------------------------------
68 //--- template implementation
69 //------------------------------------------------------------------------------
70 template <typename Coll, typename Extractor>
71 decltype(auto) util::makeValueIndex(Coll const& coll, Extractor getter) {
72 
73  using Value_t = typename Coll::value_type;
74  using Key_t
75 #if 0 // this is C++17...
76  = std::remove_reference_t<std::invoke_result_t<Extractor, Value_t>>;
77 #else // ... and this is what Clang 5.0 understands:
78  = std::remove_reference_t<decltype(getter(std::declval<Value_t>()))>;
79 #endif // 0
80 
81  using Map_t = std::map<Key_t, std::size_t>;
82 
83  Map_t index;
84  for (auto&& [ iValue, collValue ]: util::enumerate(coll)) {
85 
86  Key_t const& key = getter(collValue);
87  auto const iKey = index.lower_bound(key);
88  if ((iKey != index.end()) && (iKey->first == key)) {
89  // no guarantee that `key` supports `std::to_string()`: print only indices
90  throw std::runtime_error(
91  std::string(__func__) + ": element #" + std::to_string(iValue)
92  + " has the same key as #" + std::to_string(iKey->second)
93  );
94  }
95  index.emplace_hint(iKey, key, iValue);
96  } // for
97 
98  return index;
99 
100 } // util::makeValueIndex()
101 
102 
103 //------------------------------------------------------------------------------
104 
105 #endif // LARCOREALG_COREUTILS_MAKEVALUEINDEX_H
Definition of util::enumerate().
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
Definition: enumerate.h:69
Transparent functor that returns its argument just as passed.
Functions to help debugging by instrumenting code.
std::string to_string(WindowPattern const &pattern)
decltype(auto) makeValueIndex(Coll const &coll, Extractor getter)
Returns a map of value to index.
Code that might appear as standard C++ in the future.