LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
TupleLookupByTag.h
Go to the documentation of this file.
1 
37 #ifndef LARDATA_UTILITIES_TUPLELOOKUPBYTAG_H
38 #define LARDATA_UTILITIES_TUPLELOOKUPBYTAG_H
39 
40 // LArSoft libraries
42 
43 // C/C++ standard libraries
44 #include <tuple>
45 #include <type_traits>
46 #include <cstddef> // std::size_t
47 
66 namespace util {
67 
68  namespace details {
69 
70  //--------------------------------------------------------------------------
71  // forward declaration of implementation details
72  //--------------------------------------------------------------------------
73  //--- General utilities
74  //--------------------------------------------------------------------------
75  template <typename Target, typename... T>
77 
78  template <typename Target, typename... T>
80 
81 
82  //--------------------------------------------------------------------------
83  //--- Courtesy traits
84  //--------------------------------------------------------------------------
85  template <typename Tuple>
87 
88 
89  //--------------------------------------------------------------------------
90  //--- Tagging
91  //--------------------------------------------------------------------------
92  template <typename Tagged, typename = void>
94 
95 
96  //--------------------------------------------------------------------------
97 
98  } // namespace details
99 
100 
101  //--- BEGIN Metaprogramming --------------------------------------------------
104 
106  template <typename Target, typename... T>
108 
110  template <typename Target, typename... T>
111  constexpr unsigned int count_type_in_list_v
112  = count_type_in_list<Target, T...>();
113 
115  template <std::size_t N, typename... T>
116  using typelist_element_type = std::tuple_element<N, std::tuple<T...>>;
117 
119  template <std::size_t N, typename... T>
120  using typelist_element_t = typename typelist_element_type<N, T...>::type;
121 
122 
124  template <typename Target, typename... T>
125  using type_is_in = details::type_is_in_impl<Target, T...>;
126 
128  template <typename Target, typename... T>
129  constexpr bool type_is_in_v = type_is_in<Target, T...>();
130 
131 
133  template <typename Target, typename Tuple>
135 
137  //--- END Metaprogramming ----------------------------------------------------
138 
139 
140  //----------------------------------------------------------------------------
152  //----------------------------------------------------------------------------
190  template <
191  typename SrcTuple,
192  template <typename T, typename...> class Extractor,
193  template <typename...> class TargetClass = std::tuple
194  >
196 
197 
199  template <
200  typename SrcTuple,
201  template <typename T, typename...> class Extractor,
202  template <typename...> class TargetClass = std::tuple
203  >
206 
207 
210  template
211  <typename Tuple, template <typename...> class TargetClass = std::tuple>
213 
215  template
216  <typename Tuple, template <typename...> class TargetClass = std::tuple>
218 
219 
220  //----------------------------------------------------------------------------
250  template<
251  template <typename T, typename...> class Extractor,
252  typename Target,
253  typename Tuple
254  >
256 
258  template<
259  template <typename T, typename...> class Extractor,
260  typename Target,
261  typename Tuple
262  >
263  constexpr std::size_t index_of_extracted_type_v
265 
266 
270  template <typename Target, typename Tuple>
272 
273 
275  template <typename Target, typename Tuple>
277 
278 
279  //----------------------------------------------------------------------------
309  template<
310  template <typename T, typename...> class Extractor,
311  typename Target,
312  typename Tuple
313  >
314  using type_with_extracted_type = std::tuple_element
315  <index_of_extracted_type_v<Extractor, Target, Tuple>, Tuple>;
316 
318  template<
319  template <typename T, typename...> class Extractor,
320  typename Target,
321  typename Tuple
322  >
325 
326 
327  //----------------------------------------------------------------------------
372  template<
373  template <typename T, typename...> class Extractor,
374  typename Target,
375  typename Tuple
376  >
378 
380  template<
381  template <typename T, typename...> class Extractor,
382  typename Target,
383  typename Tuple
384  >
385  constexpr bool has_extracted_type_v
387 
388 
391  template <typename Target, typename Tuple>
393 
395  template<typename Target, typename Tuple>
397 
398 
399  //----------------------------------------------------------------------------
436  template <
437  template <typename T, typename...> class Extractor,
438  typename Target,
439  typename Tuple>
440  auto getByExtractedType(Tuple const& data) -> decltype(auto);
441 
442 
467  template <template <typename T, typename...> class Extractor, typename Tuple>
470  <extract_to_tuple_type_t<Tuple, Extractor>>
471  {};
472 
474  template <template <typename T, typename...> class Extractor, typename Tuple>
475  constexpr bool has_duplicate_extracted_types_v
477 
478 
482  template <typename Tuple>
484 
486  template <typename Tuple>
488 
489 
519  template <
520  template <typename T, typename...> class Extractor,
521  typename Target,
522  typename Tuple
523  >
525 
527  template <
528  template <typename T, typename...> class Extractor,
529  typename Target,
530  typename Tuple
531  >
532  constexpr unsigned int count_extracted_types_v
534 
535 
539  template <typename Target, typename Tuple>
541 
543  template <typename Target, typename Tuple>
544  constexpr unsigned int count_types_v = count_types<Target, Tuple>();
545 
547 
548 
596  template <typename T, typename Tag>
597  struct TaggedType: public T {
598 
599  // Forward all constructors
600  template <typename... Args>
601  TaggedType(Args&&... args): T(std::forward<Args>(args)...) {}
602 
603  using tag = Tag;
604  using tagged_type = T;
605 
606  }; // struct TaggedType
607 
608 
611  template <typename T, typename Tag>
613 
616  template <typename T, typename Tag>
618 
619 
621  template <typename Tagged>
622  struct remove_tag { using type = Tagged; };
623 
624  template <typename T, typename Tag>
625  struct remove_tag<TaggedType<T, Tag>>
626  { using type = typename TaggedType<T, Tag>::tagged_type; };
627 
629  template <typename Tagged>
631 
632 
644  template <typename Tag, typename T>
645  auto makeTagged(T& obj) -> decltype(auto)
646  { return static_cast<add_tag_t<T, Tag>&>(obj); }
647 
659  template <typename Tag, typename T>
660  auto makeTagged(T const& obj) -> decltype(auto)
661  { return static_cast<add_tag_t<T const, Tag> const&>(obj); }
662 
675  template <typename Tag, typename T>
676  auto makeTagged(T const&& obj) -> decltype(auto)
677  { return add_tag_t<T, Tag>(obj); /* copy, since it's constant */ }
678 
692  template <typename Tag, typename T>
693  auto makeTagged(T&& obj) -> decltype(auto)
694  { return add_tag_t<T, Tag>(std::move(obj)); }
695 
697  template <typename Tagged>
698  auto removeTag(Tagged& tagged) -> decltype(auto)
699  { return static_cast<remove_tag_t<Tagged>&>(tagged); }
700 
702  template <typename Tagged>
703  auto removeTag(Tagged const& tagged) -> decltype(auto)
704  { return static_cast<remove_tag_t<Tagged> const&>(tagged); }
705 
707  template <typename Tagged>
708  auto removeTag(Tagged const&& tagged) -> decltype(auto)
709  { return static_cast<remove_tag_t<Tagged> const&&>(tagged); }
710 
712  template <typename Tagged>
713  auto removeTag(Tagged&& tagged) -> decltype(auto)
714  { return static_cast<remove_tag_t<Tagged>&&>(tagged); }
715 
716 
718  template <std::size_t...>
719  struct TagN {};
720 
721 
730  template <typename Tagged>
732 
734  template <typename Tagged>
736 
738  template <typename Tagged>
739  using tag_of_t = typename tag_of<Tagged>::type;
740 
741 
743  template <typename SrcTuple>
745 
747  template <typename SrcTuple>
749 
750 
781  template <typename Tag, typename Tuple>
783 
784 
786  template <typename Tag, typename Tuple>
787  constexpr std::size_t index_of_tag_v = index_of_tag<Tag, Tuple>();
788 
789 
819  template <typename Tag, typename Tuple>
821 
822 
824  template <typename Tag, typename Tuple>
826 
827 
852  template <typename Tag, typename Tuple>
854 
856  template <typename Tag, typename Tuple>
857  constexpr bool has_tag_v = has_tag<Tag, Tuple>();
858 
859 
884  template <typename Tag, typename Tuple>
886 
888  template <typename Tag, typename Tuple>
889  constexpr unsigned int count_tags_v = count_tags<Tag, Tuple>();
890 
891 
907  template <typename Tuple>
909 
911  template <typename Tuple>
913 
914 
939  template <typename Tag, typename Tuple>
940  auto getByTag(Tuple const& data) -> decltype(auto)
941  { return getByExtractedType<TagExtractor, Tag>(data); }
942 
943 
945 
946 } // namespace util
947 
948 
949 //------------------------------------------------------------------------------
950 //--- Template implementation
951 //------------------------------------------------------------------------------
952 namespace util {
953 
954  namespace details {
955 
956  //--------------------------------------------------------------------------
957  //
958  // CAUTION: prolonged exposition to this code may result into loss of sight.
959  //
960  //--------------------------------------------------------------------------
961  //--- implementation details (most are not documented)
962  //--------------------------------------------------------------------------
963  //--- General utilities
964  //--------------------------------------------------------------------------
965  template <typename Target, typename... T>
966  struct count_type_in_list_impl: public std::integral_constant<unsigned int, 0U>
967  {};
968 
969  template <typename Target, typename First, typename... Others>
970  struct count_type_in_list_impl<Target, First, Others...>
971  : public std::integral_constant
972  <unsigned int, count_type_in_list_impl<Target, Others...>::value>
973  {};
974 
975  template <typename Target, typename... Others>
976  struct count_type_in_list_impl<Target, Target, Others...>
977  : public std::integral_constant
978  <unsigned int, count_type_in_list_impl<Target, Others...>::value + 1>
979  {};
980 
981 
982  //--------------------------------------------------------------------------
983  //--- Courtesy traits
984  //--------------------------------------------------------------------------
985 
986 
987  //--------------------------------------------------------------------------
988  //--- Tagging
989  //--------------------------------------------------------------------------
990 
991  //--------------------------------------------------------------------------
992 
993 
994  //--------------------------------------------------------------------------
995  template <typename Target, typename... T>
996  struct type_is_in_impl: public std::false_type {};
997 
998  template <typename Target, typename First, typename... Others>
999  struct type_is_in_impl<Target, First, Others...>
1000  : public std::integral_constant<bool, type_is_in_impl<Target, Others...>::value>
1001  {};
1002 
1003  template <typename Target, typename... Others>
1004  struct type_is_in_impl<Target, Target, Others...>: public std::true_type {};
1005 
1006 
1007  //--------------------------------------------------------------------------
1026  template <template <typename...> class TargetClass, template <typename T, typename...> class Extractor, typename Tuple, std::size_t I, std::size_t N, typename... T>
1028  using type = typename extract_to_tuple_type_impl<TargetClass, Extractor, Tuple, (I + 1), N, T..., typename Extractor<std::tuple_element_t<I, Tuple>>::type>::type;
1029  }; // extract_to_tuple_type_impl
1030 
1032  template <template <typename...> class TargetClass, template <typename T, typename...> class Extractor, typename Tuple, std::size_t N, typename... T>
1033  struct extract_to_tuple_type_impl<TargetClass, Extractor, Tuple, N, N, T...> {
1034  using type = TargetClass<T...>;
1035  }; // extract_to_tuple_type_impl<N>
1036 
1037 
1038  //--------------------------------------------------------------------------
1039 
1040  // TODO try alternative simple implementation:
1041  template <typename SrcTuple, template <typename T, typename...> class Extractor, template <typename...> class TargetClass, std::size_t... I>
1043  using type = TargetClass<
1044  typename Extractor<std::tuple_element_t<I, SrcTuple>>::type...
1045  >;
1046  }; // extract_to_tuple_type_impl<N>
1047 
1048 
1049  //--------------------------------------------------------------------------
1050 
1051  // Part of implementation for `index_of_extracted_type`.
1052  template <template <typename T, typename...> class Extractor, typename Target, std::size_t I, typename Elem, typename Tuple>
1054 
1055  // Part of implementation for `index_of_extracted_type`.
1056  template <template <typename T, typename...> class Extractor, typename Target, std::size_t N, std::size_t I, typename Tuple>
1058  : public index_of_extracted_type_impl<Extractor, Target, I, typename Extractor<std::tuple_element_t<I, Tuple>>::type, Tuple>
1059  {};
1060 
1061  // Part of implementation for `index_of_extracted_type`.
1062  template<template <typename T, typename...> class Extractor, typename Target, std::size_t N, typename Tuple>
1063  struct index_of_extracted_type_checked<Extractor, Target, N, N, Tuple>
1064  : public std::integral_constant<std::size_t, N>
1065  {};
1066  template <template <typename T, typename...> class Extractor, typename Target, std::size_t I, typename Elem, typename Tuple>
1069  <Extractor, Target, std::tuple_size<Tuple>::value, (I + 1), Tuple>
1070  {};
1071 
1072  // Part of implementation for `index_of_extracted_type`.
1073  template <template <typename T, typename...> class Extractor, typename Target, std::size_t I, typename Tuple>
1074  struct index_of_extracted_type_impl<Extractor, Target, I, Target, Tuple>
1075  : public std::integral_constant<std::size_t, I>
1076  {
1077  static constexpr std::size_t N = std::tuple_size<Tuple>();
1078  static_assert(I < N, "Internal logic error.");
1079  };
1080 
1081  // Part of implementation for `index_of_extracted_type`.
1082  template <template <typename T, typename...> class Extractor, typename Target, std::size_t N, std::size_t After, typename Tuple>
1084  : public index_of_extracted_type_checked<Extractor, Target, N, (After + 1), Tuple>
1085  {};
1086 
1087  // Part of implementation for `index_of_extracted_type`.
1088  template <template <typename T, typename...> class Extractor, typename Target, std::size_t N, typename Tuple>
1089  struct index_of_extracted_type_checked_after<Extractor, Target, N, N, Tuple>
1090  : public std::integral_constant<std::size_t, N>
1091  {};
1092 
1093 
1094  // Part of implementation for `index_of_extracted_type`.
1095  // This implementation relies on std::tuple_size and std::tuple_element;
1096  // an implementation assuming Tuple to be std::tuple would be more efficient...
1097  template <template <typename T, typename...> class Extractor, typename Target, typename Tuple>
1099  : public std::integral_constant<
1100  std::size_t,
1101  index_of_extracted_type_checked<Extractor, Target, std::tuple_size<Tuple>::value, 0U, Tuple>::value
1102  >
1103  {};
1104 
1105  // Part of implementation for `index_of_extracted_type`.
1106  template <template <typename T, typename...> class Extractor, typename Target, typename Tuple>
1108  static constexpr std::size_t N = std::tuple_size<Tuple>::value;
1109  static constexpr std::size_t value = index_of_type_base<Extractor, Target, Tuple>();
1110 
1111  static_assert(value < N,
1112  "The specified tuple does not have the sought type.");
1114  "The specified tuple has more than one element with the sought type.");
1115  }; // struct index_of_type_helper
1116 
1117 
1118  //--------------------------------------------------------------------------
1119  // Part of implementation of `has_duplicate_types`.
1120  template <typename Tuple, typename... T>
1121  struct has_duplicate_types_impl: public std::false_type {};
1122 
1123  template <typename Tuple, typename First, typename... Others>
1124  struct has_duplicate_types_impl<Tuple, First, Others...>
1125  : public std::integral_constant<bool,
1126  (count_type_in_tuple<First, Tuple>::value > 1U)
1127  || has_duplicate_types_impl<Tuple, Others...>::value
1128  >
1129  {};
1130 
1131 
1132  // Part of implementation of `has_duplicate_types`.
1133  template <typename Tuple>
1135 
1136  template <typename... T>
1137  struct has_duplicate_types_unwrapper<std::tuple<T...>>
1138  : public has_duplicate_types_impl<std::tuple<T...>, T...>
1139  {};
1140 
1141 
1142  //--------------------------------------------------------------------------
1143  // Part of implementation of `count_extracted_types` (might be exposed...).
1144  template <template <typename T, typename...> class Extractor, typename Target, typename... Tags>
1146  : public count_type_in_list<typename Extractor<Target>::type, Tags...>
1147  {};
1148 
1149  template <template <typename T, typename...> class Extractor, typename Target, typename... TagTuple>
1151 
1152  template <template <typename T, typename...> class Extractor, typename Target, typename... Tags>
1153  struct count_tags_in_tuple<Extractor, Target, std::tuple<Tags...>>
1154  : public count_type_in_tuple<typename Extractor<Target>::type, Tags...>
1155  {};
1156 
1157 
1158  //--------------------------------------------------------------------------
1159  //--- Tag traits
1160  //--------------------------------------------------------------------------
1161  template <typename Tagged, typename /* = void */>
1162  struct TagExtractorImpl {
1163  static_assert(always_false_type<Tagged>(), "This type is not tagged.");
1164  };
1165 
1166  template <typename Tagged>
1168  Tagged,
1169  std::enable_if_t
1170  <always_true_type<typename std::remove_reference_t<Tagged>::tag>::value>
1171  >
1172  {
1173  using type = typename std::remove_reference_t<Tagged>::tag;
1174  };
1175 
1176 
1177  //--------------------------------------------------------------------------
1178 
1179 
1180  } // namespace details
1181 
1182  //----------------------------------------------------------------------------
1183  //--- Implementation of the exposed traits
1184  //----------------------------------------------------------------------------
1185  //--- General utilities
1186  //----------------------------------------------------------------------------
1187  template <typename Target, typename Tuple>
1188  struct count_type_in_tuple
1189  {
1190  static_assert(always_false_type<Tuple>(),
1191  "count_type_in_tuple requires an instance of std::tuple");
1192  };
1193 
1194  // specialization: only works for std::tuples
1195  template <typename Target, typename... T>
1196  struct count_type_in_tuple<Target, std::tuple<T...>>
1197  : public count_type_in_list<Target, T...>
1198  {};
1199 
1200 
1201  //----------------------------------------------------------------------------
1202  //--- Courtesy traits
1203  //----------------------------------------------------------------------------
1204  template <
1205  typename SrcTuple,
1206  template <typename T, typename...> class Extractor,
1207  template <typename...> class TargetClass /* = std::tuple */
1208  >
1209  struct extract_to_tuple_type {
1210  private:
1211  static constexpr std::size_t N = std::tuple_size<SrcTuple>();
1212  public:
1213  using type = typename details::extract_to_tuple_type_impl
1214  <TargetClass, Extractor, SrcTuple, 0U, N>::type;
1215  }; // extract_to_tuple_type
1216 
1217 
1218  //----------------------------------------------------------------------------
1219  template<
1220  template <typename T, typename...> class Extractor,
1221  typename Target,
1222  typename Tuple
1223  >
1225  : public std::integral_constant<
1226  std::size_t,
1227  details::index_of_type_helper<Extractor, Target, Tuple>::value
1228  >
1229  {};
1230 
1231 
1232  //----------------------------------------------------------------------------
1233  template<
1234  template <typename T, typename...> class Extractor,
1235  typename Target,
1236  typename Tuple
1237  >
1238  struct has_extracted_type
1239  : public std::integral_constant<
1240  bool,
1241  (details::index_of_type_base<Extractor, Target, Tuple>::value < std::tuple_size<Tuple>::value)
1242  >
1243  {};
1244 
1245 
1246  //----------------------------------------------------------------------------
1247  template <
1248  template <typename T, typename...> class Extractor,
1249  typename Target,
1250  typename Tuple
1251  >
1252  struct count_extracted_types
1253  : public count_type_in_tuple
1254  <Target, extract_to_tuple_type_t<Tuple, Extractor>>
1255  {};
1256 
1257 
1258  //----------------------------------------------------------------------------
1259  template <
1260  template <typename T, typename...> class Extractor,
1261  typename Target,
1262  typename Tuple>
1263  auto getByExtractedType(Tuple const& data) -> decltype(auto)
1264  {
1265  using std::get;
1266  return get<index_of_extracted_type_v<Extractor, Target, Tuple>>(data);
1267  }
1268 
1269 
1270  //----------------------------------------------------------------------------
1271  //--- Tagging utilities
1272  //----------------------------------------------------------------------------
1273 
1274  //----------------------------------------------------------------------------
1275 } // namespace util
1276 
1277 
1278 //------------------------------------------------------------------------------
1279 
1280 
1281 #endif // LARDATA_UTILITIES_TUPLELOOKUPBYTAG_H
1282 
auto getByTag(Tuple const &data) -> decltype(auto)
Returns the object with the specified tag.
TaggedType(Args &&...args)
Namespace for general, non-LArSoft-specific utilities.
Definition: PIDAAlg.h:17
Counts the elements of a tuple-like type containing a Target type.
Basic C++ metaprogramming utilities.
A type with a specified tag.
typename tag_of< Tagged >::type tag_of_t
Direct access to the type in tag_of.
auto removeTag(Tagged &tagged) -> decltype(auto)
"Converts" a tagged type back to its original type.
std::tuple_element< index_of_extracted_type_v< Extractor, Target, Tuple >, Tuple > type_with_extracted_type
Returns the element type in Tuple with the specified type.
TargetClass< typename Extractor< std::tuple_element_t< I, SrcTuple >>::type... > type
constexpr unsigned int count_tags_v
Direct access to the value in count_tags.
STL namespace.
constexpr bool type_is_in_v
Direct access to the value in type_is_in.
constexpr unsigned int count_type_in_list_v
Direct access to the value in count_type_in_list.
Holds whether the Target type is element of the specified std::tuple.
typename TaggedType< T, Tag >::tagged_type type
typename type_with_extracted_type< Extractor, Target, Tuple >::type type_with_extracted_type_t
Direct access to the value in type_with_extracted_type.
Extracts the tag from a type.
Tag class parametrized by a sequence of numbers.
void * Tuple
Definition: DBFolder.h:13
typename add_tag< T, Tag >::type add_tag_t
constexpr bool has_extracted_type_v
Direct access to the value in has_extracted_type.
Tag tag
Tag of this object.
constexpr std::size_t index_of_tag_v
Direct access to the value in index_of_tag.
A std::false_type with a template argument.
Definition: MetaUtils.h:88
constexpr unsigned int count_extracted_types_v
Direct access to the value in count_extracted_types.
std::tuple_element< N, std::tuple< T... >> typelist_element_type
Returns the N type of the type list.
typename extract_to_tuple_type_impl< TargetClass, Extractor, Tuple,(I+1), N, T..., typename Extractor< std::tuple_element_t< I, Tuple >>::type >::type type
typename remove_tag< Tagged >::type remove_tag_t
Direct access to the type contained in remove_tag.
constexpr bool has_duplicate_types_v
Direct access to the value in has_duplicate_types.
typename typelist_element_type< N, T... >::type typelist_element_t
Direct access to the value in typelist_element_type.
Trait holding the type contained in a TaggedType (or the type itself).
typename to_tuple< Tuple, TargetClass >::type to_tuple_t
Direct access to the type in to_tuple.
Trait holding whether an element in Tuple type contains Target.
typename details::extract_to_tuple_type_impl< TargetClass, Extractor, SrcTuple, 0U, N >::type type
Traits holding whether elements of Tuple have duplicate types.
constexpr bool has_type_v
Direct access to the value in has_type.
type_with_extracted_type< TagExtractor, Tag, Tuple > type_with_tag
Trait holding the type of the element of Tuple with tag Tag.
T tagged_type
Type of the object which was tagged.
Returns type TargetClass<U...> from a SrcTuple<T...>.
auto makeTagged(T &obj) -> decltype(auto)
"Converts" obj to an object with tag Tag.
std::string value(boost::any const &)
Returns the index of the element in Tuple with the specified type.
typename type_with_tag< Tag, Tuple >::type type_with_tag_t
Direct access to the value in type_with_tag.
constexpr std::size_t index_of_extracted_type_v
Direct access to the value in index_of_extracted_type.
typename extract_to_tuple_type< SrcTuple, Extractor, TargetClass >::type extract_to_tuple_type_t
Direct access to the type in extract_to_tuple_type.
Implementation for extract_to_tuple_type.
constexpr bool has_duplicate_tags_v
Direct access to the value in has_duplicate_tags.
constexpr bool has_duplicate_extracted_types_v
Direct access to the value in has_duplicate_extracted_types.
constexpr unsigned int count_types_v
Direct access to the value in count_extracted_types.
constexpr std::size_t index_of_type_v
Direct access to the value in index_of_type.
auto getByExtractedType(Tuple const &data) -> decltype(auto)
Returns the value of the element containing the specified type.
typename extract_tags< SrcTuple >::type extract_tags_t
Direct access to the type in extract_tags.
constexpr bool has_tag_v
Direct access to the value in has_tag.