CollectionProxyMaker.h
Go to the documentation of this file.
1 /**
2  * @file lardata/RecoBaseProxy/ProxyBase/CollectionProxyMaker.h
3  * @brief Infrastructure for the creation of a collection proxy.
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date July 27, 2017
6  * @see lardata/RecoBaseProxy/ProxyBase/getCollection.h
7  *
8  * This library is header-only.
9  */
10 
11 #ifndef LARDATA_RECOBASEPROXY_PROXYBASE_COLLECTIONPROXYMAKER_H
12 #define LARDATA_RECOBASEPROXY_PROXYBASE_COLLECTIONPROXYMAKER_H
13 
14 // LArSoft libraries
16 #include "larcorealg/CoreUtils/ContainerMeta.h" // util::collection_value_t, ...
17 #include "larcorealg/CoreUtils/MetaUtils.h" // util::always_true_type
18 
19 // framework libraries
21 
22 // C/C++ standard
23 #include <vector>
24 
25 
26 namespace proxy {
27 
28  // --- BEGIN Collection proxy infrastructure ---------------------------------
29  /// @addtogroup LArSoftProxyCollections
30  /// @{
31 
32  //----------------------------------------------------------------------------
33  /**
34  * @brief Collection of data type definitions for collection proxies.
35  * @tparam Proxy type of proxy the traits refer to
36  * @tparam Selector specialization helper type
37  *
38  * Expected traits:
39  * * `main_collection_t`: type of the main data product collection
40  * * `main_element_t`: type contained in the main data product collection
41  * * `main_collection_proxy_t`: type wrapping the main data product collection
42  * * `collection_proxy_impl_t`: type of implementation object used for the
43  * proxy; to use `proxy::CollectionProxy`, define this as:
44  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
45  * template <typename... Args>
46  * using collection_proxy_impl_t = proxy::CollectionProxyFromArgs<Args...>;
47  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
48  * This trait is treated as optional by the default `CollectionProxyMaker`
49  * implementation, which uses `proxy::CollectionProxy` if the trait is
50  * missing.
51  *
52  * Note that the `Proxy` type is expected to be the same type as used in
53  * `getCollection()` calls, and does not need to match the actual type of a
54  * proxy collection.
55  */
56  template <typename Proxy, typename Selector = Proxy>
58  static_assert
59  (util::always_true_type<Proxy>(), "This class requires specialization.");
60  };
61 
62 
63  //----------------------------------------------------------------------------
64  /**
65  * @brief Class to assemble the required proxy.
66  * @tparam CollProxy a type characterizing the produced proxy
67  *
68  * This is a base class suitable for deriving `CollectionProxyMaker`,
69  * which is used by `getCollection()` to create the requested proxy.
70  * Deriving a specialization of `CollectionProxyMaker` from
71  * `CollectionProxyMakerBase` provides some basic definitions and
72  * functionality that might be tedious to copy.
73  *
74  * In this, which can be considered as the default implementation of
75  * `CollectionProxyMaker`, the template argument `CollProxy` is expected to
76  * have the interface of `CollectionProxy`.
77  * The arguments required are documented in the implementation of the `make()`
78  * function. Note that the type of proxy returned does not need to be
79  * `CollProxy`, but is in fact an instance of `proxy::CollectionProxy`.
80  *
81  * @attention This class is not meant to be specialized.
82  */
83  template <typename CollProxy>
85 
86  /// Traits of the collection proxy for the collection proxy maker.
88 
89  /// Type of main collection proxy.
90  using main_collection_proxy_t = typename traits_t::main_collection_proxy_t;
91 
92  /// Type returned by the main collection indexing operator.
93  using main_element_t = typename traits_t::main_element_t;
94 
95  /// Type of element of the main collection.
96  using main_collection_t = typename traits_t::main_collection_t;
97 
98  /**
99  * @brief Creates and returns a collection proxy based on `CollProxy` and
100  * with the requested associated data.
101  * @tparam Event type of the event to read the information from
102  * @tparam WithArgs type of arguments for associated data
103  * @param event event to read the information from
104  * @param tag input tag of the main data product
105  * @param withArgs optional associated objects to be included
106  * @return a collection proxy from data as retrieved via `tag`
107  *
108  * For each argument in `withArgs`, an action is taken. Usually that is to
109  * add an association to the proxy.
110  *
111  * Only a few associated data collections are supported:
112  * * `withAssociated<Aux>()` (optional argument: hit-track association
113  * tag, as track by default): adds to the proxy an association to the
114  * `Aux` data product (see `withAssociated()`)
115  *
116  */
117  template <typename Event, typename... WithArgs>
118  static auto make
119  (Event const& event, art::InputTag const& tag, WithArgs&&... withArgs);
120 
121  }; // struct CollectionProxyMakerBase<>
122 
123 
124  //----------------------------------------------------------------------------
125  /**
126  * @brief Class to assemble the required proxy.
127  * @tparam CollProxy a type characterizing the produced proxy
128  *
129  * This class is used by `getCollection()` to create the requested proxy.
130  * The required interface for this class is:
131  * * `make()`: a static method returning the collection proxy, matching the
132  * signature
133  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
134  * template <typename Event, typename... Args>
135  * auto make(Event const&, Args&&...);
136  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
137  * where the first argument will be the event to read the information from.
138  *
139  * A default implementation is provided as `proxy::CollectionProxyMakerBase`.
140  * Specializations of `proxy::CollectionProxyMaker` may choose to derive from
141  * `proxy::CollectionProxyMakerBase` as well, for convenience.
142  */
143  template <typename CollProxy>
145 
146 
147  /// @}
148  // --- END Collection proxy infrastructure -----------------------------------
149 
150 
151  //----------------------------------------------------------------------------
152  //--- specializations of CollectionProxyMakerTraits
153  //----------------------------------------------------------------------------
154 
155  template <typename T>
157 
158  /// Type of element of the main collection.
159  using main_collection_t = std::vector<T>;
160 
161  /// Type returned by the main collection indexing operator.
163 
164  /// Type of main collection proxy.
167 
168  }; // CollectionProxyMakerTraits<std::vector<T>>
169 
170 
171  template <typename MainColl>
173  /// Type of main collection proxy.
175 
176  /// Type returned by the main collection indexing operator.
178 
179  /// Type of element of the main collection.
180  using main_collection_t
182 
183  }; // CollectionProxyMakerTraits<CollectionProxy>
184 
185 
186  // ---------------------------------------------------------------------------
187 
188 } // namespace proxy
189 
190 
191 
192 // -----------------------------------------------------------------------------
193 // --- Template implementation
194 // -----------------------------------------------------------------------------
195 namespace proxy {
196 
197  namespace details {
198 
199  // -------------------------------------------------------------------------
200  //
201  // We need to discover whether the trait class contains a
202  // `collection_proxy_impl_t` type. Unfortunately, that is not a plain type
203  // but rather a template type (it is expected to take the same template
204  // arguments as `proxy::CollectionProxy`).
205  //
206  // Since Gianluca is not able to detect the presence of a templated type in
207  // a class, but only of fully specified type, the following machinery is in
208  // place. At the time we need to know the `collection_proxy_impl_t` type, we
209  // are trying to create one and therefore we know the full argument set for
210  // it already (let's call it `Args...`, that is `MainColl` plus
211  // `AuxColls...`). Then, we test the presence of
212  // `collection_proxy_impl_t<Args...>` instead of just
213  // `collection_proxy_impl_t`.
214  // An additional complication is the presence of a parameter pack, that
215  // impedes the usual pattern of having `std::enable_if_t` as the last,
216  // optional template parameter (`Args` must be the last). So we give up the
217  // elegant feature of having a default value, and we force the caller to
218  // explicitly spell it: `void` (always that one).
219  // We absorb this ugliness and the need for the usual and cumbersome
220  // `typename ...::type` in the definition of
221  // `CollectionProxyImplFromTraits_t`, which should be the only access point
222  // to this machinery.
223  // About the naming: a "collection proxy" is the final proxy class.
224  // `CollectionProxy` is also the name, already taken, of the class we
225  // provide as reference for that role. So I have called the role an
226  // "implementation" of the "collection proxy" idea, and `CollectionProxy` is
227  // in fact an implementation (the "standard" one) of that idea.
228  // The name of that idea in the proxy traits is `collection_proxy_impl_t`.
229  // `CollectionProxyImpl` is supposed to be a generic name for that concept,
230  // and the utility `CollectionProxyImplFromTraits` is in charge of
231  // extracting it from the traits. This utility also needs an implementation,
232  // hence the second "Impl": `CollectionProxyImplFromTraitsImpl`. Urgh.
233  //
234  // I don't know whether to be worried that the explanation of this code is
235  // longer than the code itself...
236  //
237  template <typename Traits, typename, typename... Args>
239  using type = CollectionProxyFromArgs<Args...>;
240  };
241 
242  template <typename Traits, typename... Args>
244  Traits,
245  std::enable_if_t<util::always_true_v
246  <typename Traits::template collection_proxy_impl_t<Args...>>
247  >,
248  Args...
249  >
250  {
251  using type = typename Traits::template collection_proxy_impl_t<Args...>;
252  };
253 
254  /// `Traits::collection_proxy_impl_t` if that (template) type exists,
255  /// `proxy::CollectionProxy` otherwise.
256  template <typename Traits, typename... Args>
258  = typename CollectionProxyImplFromTraitsImpl<Traits, void, Args...>::type;
259 
260 
261  // -------------------------------------------------------------------------
262  template <typename Traits, typename... Args>
264  using collection_proxy_impl_t
266  return collection_proxy_impl_t(std::forward<Args>(args)...);
267  } // createCollectionProxyFromTraits()
268 
269 
270  // -------------------------------------------------------------------------
271 
272  } // namespace details
273 
274 
275  // ---------------------------------------------------------------------------
276  // --- CollectionProxyMakerBase implementation
277  // ---------------------------------------------------------------------------
278  template <typename CollProxy>
279  template <typename Event, typename... WithArgs>
281  (Event const& event, art::InputTag const& tag, WithArgs&&... withArgs)
282  {
283  auto mainHandle = event.template getValidHandle<main_collection_t>(tag);
284 
285  // The actual type of collection proxy implementation is extracted from
286  // the traits of the proxy (`collection_proxy_impl_t`), but if that is not
287  // provided a default implementation, `proxy::CollectionProxy`, is used:
288  return details::createCollectionProxyFromTraits<traits_t>(
289  *mainHandle,
290  withArgs.template createAuxProxyMaker<main_collection_proxy_t>
291  (event, mainHandle, tag)...
292  );
293  } // CollectionProxyMakerBase<>::make<>()
294 
295 
296  // ---------------------------------------------------------------------------
297 
298 } // namespace proxy
299 
300 #endif // LARDATA_RECOBASEPROXY_PROXYBASE_COLLECTIONPROXYMAKER_H
auto createCollectionProxyFromTraits(Args &&...args)
Collection of data type definitions for collection proxies.
Basic C++ metaprogramming utilities.
MainColl main_collection_t
Type of the original collection.
Class to assemble the required proxy.
typename details::TemplateAdaptorOnePlus< CollectionProxy, Args... >::type CollectionProxyFromArgs
util::collection_value_t< MainColl > main_element_t
Type of the elements in the original collection.
Define the traits of proxy::Tracks proxy.
Definition: Track.h:1203
STL namespace.
typename traits_t::main_element_t main_element_t
Type returned by the main collection indexing operator.
static QCString args
Definition: declinfo.cpp:674
typename traits_t::main_collection_proxy_t main_collection_proxy_t
Type of main collection proxy.
Base representation of a collection of proxied objects.
Wrapper for the main collection of a proxy.
typename main_collection_proxy_t::main_collection_t main_collection_t
Type of element of the main collection.
static auto make(Event const &event, art::InputTag const &tag, WithArgs &&...withArgs)
Creates and returns a collection proxy based on CollProxy and with the requested associated data...
Utilities for the collection proxy object.
Class to assemble the required proxy.
A std::true_type with a template argument.
Definition: MetaUtils.h:145
unique_ptr< InputSource > make(ParameterSet const &conf, InputSourceDescription &desc)
Definition: types.h:32
static QCString type
Definition: declinfo.cpp:672
util::collection_value_t< main_collection_t > main_element_t
Type returned by the main collection indexing operator.
std::vector< T > main_collection_t
Type of element of the main collection.
typename traits_t::main_collection_t main_collection_t
Type of element of the main collection.
typename collection_value_type< Coll >::type collection_value_t
Type contained in the collection Coll.
Definition: ContainerMeta.h:65
typename main_collection_proxy_t::main_element_t main_element_t
Type returned by the main collection indexing operator.
C++ metaprogramming utilities for dealing with containers.
typename CollectionProxyImplFromTraitsImpl< Traits, void, Args... >::type CollectionProxyImplFromTraits_t
Event finding and building.