ServiceUtil.h
Go to the documentation of this file.
1 /**
2  * @file ServiceUtil.h
3  * @brief Utilities related to art service access
4  * @author Jonathan Paley (jpaley@fnal.gov),
5  * Gianluca Petrillo (petrillo@fnal.gov)
6  *
7  * This library is currently a pure header.
8  * It provides:
9  *
10  * - lar::providerFrom(), extracting and returning the provider from a single
11  * service
12  * - lar::providersFrom(), extracting and returning providers from a set of
13  * services
14  * - lar::providersFrom_t, a type defined as a provider pack with the providers
15  * from all the specified services
16  *
17  */
18 
19 #ifndef LARCORE_COREUTILS_SERVICEUTIL_H
20 #define LARCORE_COREUTILS_SERVICEUTIL_H
21 
22 // LArSoft libraries
25 
26 // framework libraries
29 #include "cetlib_except/demangle.h"
30 
31 // C/C++ standard libraries
32 #include <type_traits> // std::decay<>, std::is_same<>, std::add_const_t<>
33 #include <typeinfo>
34 
35 
36 namespace lar {
37 
38  namespace details {
39  template <typename PROVIDER>
41 
42  template <typename... Services>
44 
45  } // namespace details
46 
47 
48  /** **************************************************************************
49  * @brief Returns a constant pointer to the provider of specified service.
50  * @tparam T type of the service
51  * @return a constant pointer to the provider of specified service
52  * @throws art::Exception (category `art::errors::NotFound`) if pointer is null
53  *
54  * This function relies on the following service and provider interface:
55  * - provider is not movable nor copyable
56  * - service contains a type `provider_type` defined as the class of the
57  * service provider
58  * - service contains a method "provider()" that returns a non-null pointer
59  * to a service provider; the service provider is owned and managed by
60  * the service, and the caller is not responsible of regulating the object
61  * lifetime, nor it should attempt to
62  *
63  * Violations of the protocol yield compilation errors (in case non-compliance
64  * can be statically detected), or throw of exceptions.
65  *
66  * Example of usage:
67  *
68  * auto const* geom = lar::providerFrom<geo::Geometry>();
69  *
70  * retrieves the service provider for LArSoft geometry.
71  * This requires the inclusion of "Geometry/Geometry.h" header, where the
72  * service is declared. Typically, both ServiceUtil.h and the header of the
73  * provider class are included in the service header.
74  *
75  */
76  template <typename T>
77  typename T::provider_type const* providerFrom()
78  {
79  using Service_t = std::add_const_t<T>;
80  using Provider_t = typename Service_t::provider_type;
81 
83 
84  // retrieve the provider
86  Provider_t const* const pProvider { h->provider() };
87  if (!pProvider) {
89  << "ServiceHandle <" << cet::demangle_symbol(typeid(Service_t).name())
90  << "> offered a null provider";
91  }
92 
93  return pProvider;
94 
95  } // providerFrom()
96 
97 
98  /** **************************************************************************
99  * @brief Returns a lar::ProviderPack with providers from all services
100  * @tparam Services a list of service types
101  * @return a lar::ProviderPack with providers from all specified services
102  * @throws art::Exception as lar::providerFrom()
103  * @see lar::providerFrom()
104  *
105  * This function relies on `lar::providerFrom()` to extract providers from
106  * all the specified services.
107  * The parameter pack stores the providers in the same order as the services
108  * were specified, but this is not very relevant since provider packs can
109  * be implicitly converted in other provider packs with the same providers
110  * in a different order.
111  *
112  * Example of usage:
113  *
114  * prov->setup
115  * (lar::providersFrom<geo::Geometry, detinfo::LArPropertiesService>());
116  *
117  * retrieves the service providers for LArSoft geometry and
118  * `LArPropertiesService`, and passes them as a provider pack to a setup()
119  * method, presumably from a algorithm or service provider that needs them.
120  * This requires the inclusion of "Geometry/Geometry.h" and
121  * "LArPropertiesService.h" headers, where the services are declared.
122  * Typically, both ServiceUtil.h and the header of the provider class are
123  * included in the service headers.
124  */
125  template <typename... Services>
128 
129 
130  /** **************************************************************************
131  * @brief Type of a provider pack with a provider from each of the Services
132  * @tparam Services the list of services to extract the provider type of
133  *
134  * Example of usage in a art service class declaration:
135  *
136  * using needed_providers_t = lar::providersFrom_t
137  * <geo::Geometry, detinfo::LArPropertiesService>;
138  *
139  */
140  template <typename... Services>
141  using providersFrom_t
142  = lar::ProviderPack<typename Services::provider_type...>;
143 
144 
145 
146  //----------------------------------------------------------------------------
147  namespace details {
148  /// Compiles only if PROVIDER class satisfied service provider requirements
149  template <typename PROVIDER>
151 
152  using provider_type = PROVIDER;
153 
154  // static checks on provider class: not copiable nor movable
155  static_assert(
157  "Service provider classes must not be copiable"
158  );
159  static_assert(
161  "Service provider classes must not be copiable"
162  );
163  static_assert(
165  "Service provider classes must not be movable"
166  );
167  static_assert(
169  "Service provider classes must not be movable"
170  );
171 
172  }; // ServiceProviderRequirementsChecker
173 
174 
175  template <typename SERVICE>
177 
178  // require SERVICE::provider_type to be a type
179  using provider_type = typename SERVICE::provider_type;
180 
181  // expected type for SERVICE::provider() method
182  using provider_func_type = provider_type const* (SERVICE::*)() const;
183 
184  /// Checker for the provider
186 
187  // check the provider() method
188  static_assert(
189  std::is_same<decltype(&SERVICE::provider), provider_func_type>::value,
190  "provider() method has unsupported signature"
191  );
192 
193  }; // ServiceRequirementsChecker
194 
195 
196  //--------------------------------------------------------------------------
197  template <typename First, typename... Others>
198  struct ProviderPackExtractor<First, Others...> {
199  static ProviderPack<
200  typename First::provider_type, typename Others::provider_type...
201  >
203  {
204  return {
206  lar::providerFrom<First>()
207  };
208  }
209  };
210 
211 
212  template <typename Service>
213  struct ProviderPackExtractor<Service> {
214  static auto parameterPack()
215  { return lar::makeProviderPack(lar::providerFrom<Service>()); }
216  };
217 
218 
219  } // namespace details
220 
221 } // namespace lar
222 
223 #endif //#LARCORE_COREUTILS_SERVICEUTIL_H
static QCString name
Definition: declinfo.cpp:673
typename SERVICE::provider_type provider_type
Definition: ServiceUtil.h:179
T::provider_type const * providerFrom()
Returns a constant pointer to the provider of specified service.
Definition: ServiceUtil.h:77
Defines classes that can&#39;t be copied nor moved.
virtual const provider_type * provider() const override
static ProviderPack< typename First::provider_type, typename Others::provider_type... > parameterPack()
Definition: ServiceUtil.h:202
Data structure containing constant pointers to classes.
ServiceProviderRequirementsChecker< provider_type > provider_checker
Checker for the provider.
Definition: ServiceUtil.h:185
ProviderPack< Providers... > makeProviderPack(Providers const *...providers)
Function to create a ProviderPack from the function arguments.
Definition: ProviderPack.h:272
Compiles only if PROVIDER class satisfied service provider requirements.
Definition: ServiceUtil.h:150
provider_type const *(SERVICE::*)() const provider_func_type
Definition: ServiceUtil.h:182
auto providersFrom()
Returns a lar::ProviderPack with providers from all services.
Definition: ServiceUtil.h:126
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
LArSoft-specific namespace.
Container for a list of pointers to providers.
Definition: ProviderPack.h:114