ProviderPack.h
Go to the documentation of this file.
1 /**
2  * @file ProviderPack.h
3  * @brief Data structure containing constant pointers to classes
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date November 20th, 2015
6  * @version 1.0
7  *
8  * This is a header-only library.
9  * It depends only on standard C++ and does not require additional linkage.
10  */
11 
12 
13 #ifndef DETECTORINFO_PROVIDERPACK_H
14 #define DETECTORINFO_PROVIDERPACK_H
15 
16 
17 // C/C++ standard library
18 #include <tuple>
19 #include <type_traits>
20 #include <limits>
21 
22 
23 namespace gar {
24 
25  namespace details {
26 
27  template <typename... Types>
29 
30 
31  template <typename Key, typename... Types>
33 
34  /**
35  * @brief Hosts the index of type FindType in the list of types AmongTypes
36  * @tparam FindType the type to find
37  * @tparam AmongTypes the list of types
38  *
39  * If FindType type is not any of AmongTypes typesm a compilation error
40  * message (static assertion) is issued.
41  * Otherwise, the class has a `value` member pointing to the index of
42  * FindType among AmongTypes.
43  * This value is suct that this assertion is valid:
44  *
45  * std::is_same<
46  * FindType,
47  * typename std::tuple_element<
48  * index_with_type<FindType, AmongTypes...>::value,
49  * std::tuple<AmongTypes...>
50  * >
51  * >::value
52  *
53  */
54  template <typename FindType, typename... AmongTypes>
56 
57 
58  /// Implementation detail for the extraction constructor
59  template <typename DestPack, typename SourcePack, typename... ExtractProviders>
60  struct SetFrom;
61 
62  } // namespace details
63 
64 
65  /** **************************************************************************
66  * @brief Container for a list of pointers to providers
67  * @tparam Providers types of the providers in the parameter pack
68  *
69  * The pointers are stored as constant.
70  * Note that this container can host any type of objects, and it has
71  * "provider" in the name because the reason it was written was to provide
72  * a fast way to specify a set of GArSoft service providers.
73  * The only limitation is that there should be only one object per type.
74  * Pointed objects are not owned by this class.
75  *
76  * A a;
77  * B b;
78  * C c;
79  * D d;
80  * ProviderPack<A, B, C> pack(&a, &b, &c);
81  *
82  * // obtain a constant pointerto b from pack:
83  * B const* b_ptr = pack.get<B>();
84  *
85  * if (pack.has<D>()) std::cerr << "Unexpected!" << std::endl;
86  *
87  * (note that the latter check can be coded as a static assert)
88  */
89  template <typename... Providers>
90  class ProviderPack {
92  "Providers in ProviderPack are repeated");
93 
94  using this_type = ProviderPack<Providers...>; ///< alias of this class
95 
96  /// type used for storage of the pointers
97  using tuple_type = std::tuple<Providers const*...>;
98 
99  public:
100  /// Default constructor: a null provider pointer for each type
101  ProviderPack() = default;
102 
103  /// Constructor: stores a provider pointer for each type
104  ProviderPack(Providers const* ...provider_ptrs): providers(provider_ptrs...)
105  {}
106 
107  /**
108  * @brief Constructor: extracts the providers from anothe parameter pack
109  * @tparam OtherProviders list of the providers of the source provider pack
110  * @param from where to copy the information from
111  *
112  * This constructor requires all the providers we need to be present
113  * in the source provider pack.
114  */
115  template<typename... OtherProviders>
117  {
119  <this_type, ProviderPack<OtherProviders...>, Providers...>
120  (*this, from);
121  }
122 
123  /**
124  * @brief Constructor: extracts the providers from anothe parameter pack
125  * @tparam OtherProviders list of the providers of the source provider pack
126  * @param providers all the providers needed (or more)
127  *
128  * This constructor requires all the providers we need to be present
129  * in the source provider pack.
130  */
131  template<typename... OtherProviders>
132  ProviderPack(OtherProviders const*... providers_tmp)
133  {
135  <this_type, ProviderPack<OtherProviders...>, Providers...>
136  (*this, ProviderPack<OtherProviders...>(providers_tmp...));
137  }
138 
139  /// Returns the provider with the specified type
140  template <typename Provider>
141  Provider const* get() const
142  {
143  return std::get<details::index_with_type<Provider, Providers...>::value>
144  (providers);
145  } // get<>()
146 
147 
148  /// Sets the provider with the specified type
149  template <typename Provider>
150  void set(Provider const* provider_ptr)
151  {
152  std::get<details::index_with_type<Provider, Providers...>::value>
153  (providers)
154  = provider_ptr;
155  } // set<>()
156 
157  /// Returns whether there is a provider with the specified type
158  template <typename Provider>
159  static constexpr bool has()
160  {
161  return details::index_with_type_impl<Provider, Providers...>::value
162  < sizeof...(Providers);
163  } // has<>()
164 
165  private:
166 
167  tuple_type providers; ///< container of the pointers, type-safe
168 
169  }; // class ProviderPack
170 
171 
172  /**
173  * @brief Function to create a ParameterPack from the function arguments
174  * @tparam Providers types of the providers in the parameter pack
175  * @param providers constant pointers to the providers
176  * @return a ParameterPack object containing all the specified providers
177  *
178  * This is an convevience function to reduce the typing needed to instantiate
179  * a ParameterPack.
180  */
181  template <typename... Providers>
182  ProviderPack<Providers...> makeProviderPack(Providers const* ...providers)
183  { return ProviderPack<Providers...>(providers...); }
184 
185 
186 } // namespace lar
187 
188 
189 //------------------------------------------------------------------------------
190 //--- Implementation details
191 //---
192 namespace gar {
193  namespace details {
194 
195  //--------------------------------------------------------------------------
196  //--- has_duplicate_types
197  //---
198  template <typename Key, typename... Types>
199  struct has_duplicate_types<Key, Types...>:
200  public std::integral_constant<
201  bool,
202  index_with_type_impl<Key, Types...>::value < sizeof...(Types)
203  || has_duplicate_types<Types...>::value
204  >
205  {};
206 
207  template <>
208  struct has_duplicate_types<>: public std::false_type {};
209 
210 
211  //--------------------------------------------------------------------------
212  //--- index_with_type
213  //---
214  /// Generic template, to glue the two special cases;
215  /// in general, this will have in value field the index in Types of the type
216  /// Key, or a number larger than the number if types in Types if Key type
217  /// is not present among Types.
218  template <typename Key, typename... Types>
219  struct index_with_type_impl;
220 
221  // common case: one or more types
222  template <typename Key, typename FirstType, typename... Types>
223  struct index_with_type_impl<Key, FirstType, Types...>:
224  public std::integral_constant <size_t,
225  std::is_same<Key, FirstType>::value
226  ? 0
227  : index_with_type_impl<Key, Types...>::value + 1
228  >
229  {};
230 
231  // special case: no type; this means failure
232  template <typename Key>
233  struct index_with_type_impl<Key>: public std::integral_constant <size_t, 0U>
234  {};
235 
236 
237  template <typename FindType, typename... AmongTypes>
238  struct index_with_type:
239  public std::integral_constant
240  <size_t, index_with_type_impl<FindType, AmongTypes...>::value>
241  {
242  static_assert(
243  index_with_type<FindType, AmongTypes...>::value < sizeof...(AmongTypes),
244  "Required type is not present"
245  );
246  }; // index_with_type
247 
248  //--------------------------------------------------------------------------
249  //--- SetFrom
250  //---
251  template <
252  typename DestPack, typename SourcePack,
253  typename FirstProvider, typename... OtherProviders
254  >
255  struct SetFrom<DestPack, SourcePack, FirstProvider, OtherProviders...> {
256  SetFrom(DestPack& pack, SourcePack const& from)
257  {
258  pack.set(from.template get<FirstProvider>());
259  SetFrom<DestPack, SourcePack, OtherProviders...>(pack, from);
260  }
261  }; // SetFrom<First, Others...>
262 
263  template <typename DestPack, typename SourcePack>
264  struct SetFrom<DestPack, SourcePack> {
265  SetFrom(DestPack&, SourcePack const&) {}
266  };
267 
268  //--------------------------------------------------------------------------
269 
270  } // namespace details
271 
272 
273  //----------------------------------------------------------------------------
274  //--- ProviderPack
275  //---
276 
277  //----------------------------------------------------------------------------
278 
279 } // namespace gar
280 
281 #endif // DETECTORINFO_PROVIDERPACK_H
has_duplicate_extracted_types< self_type, Tuple > has_duplicate_types
ProviderPack(OtherProviders const *...providers_tmp)
Constructor: extracts the providers from anothe parameter pack.
Definition: ProviderPack.h:132
Implementation detail for the extraction constructor.
Definition: ProviderPack.h:60
Container for a list of pointers to providers.
Definition: ProviderPack.h:90
ProviderPack(ProviderPack< OtherProviders... > const &from)
Constructor: extracts the providers from anothe parameter pack.
Definition: ProviderPack.h:116
std::tuple< Providers const *... > tuple_type
type used for storage of the pointers
Definition: ProviderPack.h:97
static constexpr bool has()
Returns whether there is a provider with the specified type.
Definition: ProviderPack.h:159
General GArSoft Utilities.
Hosts the index of type FindType in the list of types AmongTypes.
Definition: ProviderPack.h:55
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
ProviderPack< Providers... > makeProviderPack(Providers const *...providers)
Function to create a ParameterPack from the function arguments.
Definition: ProviderPack.h:182
tuple_type providers
container of the pointers, type-safe
Definition: ProviderPack.h:167
ProviderPack(Providers const *...provider_ptrs)
Constructor: stores a provider pointer for each type.
Definition: ProviderPack.h:104