LArSoft  v09_90_00
Liquid Argon Software toolkit - https://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 <cstddef> // std::size_t
45 #include <tuple>
46 #include <type_traits>
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  //--- Courtesy traits
83  //--------------------------------------------------------------------------
84  template <typename Tuple>
86 
87  //--------------------------------------------------------------------------
88  //--- Tagging
89  //--------------------------------------------------------------------------
90  template <typename Tagged, typename = void>
92 
93  //--------------------------------------------------------------------------
94 
95  } // namespace details
96 
97  //--- BEGIN Metaprogramming --------------------------------------------------
100 
102  template <typename Target, typename... T>
104 
106  template <typename Target, typename... T>
107  constexpr unsigned int count_type_in_list_v = count_type_in_list<Target, T...>();
108 
110  template <std::size_t N, typename... T>
111  using typelist_element_type = std::tuple_element<N, std::tuple<T...>>;
112 
114  template <std::size_t N, typename... T>
116 
118  template <typename Target, typename... T>
119  using type_is_in = details::type_is_in_impl<Target, T...>;
120 
122  template <typename Target, typename... T>
123  constexpr bool type_is_in_v = type_is_in<Target, T...>();
124 
126  template <typename Target, typename Tuple>
128 
130  //--- END Metaprogramming ----------------------------------------------------
131 
132  //----------------------------------------------------------------------------
143  //----------------------------------------------------------------------------
181  template <typename SrcTuple,
182  template <typename T, typename...>
183  class Extractor,
184  template <typename...> class TargetClass = std::tuple>
186 
188  template <typename SrcTuple,
189  template <typename T, typename...>
190  class Extractor,
191  template <typename...> class TargetClass = std::tuple>
194 
197  template <typename Tuple, template <typename...> class TargetClass = std::tuple>
199 
201  template <typename Tuple, template <typename...> class TargetClass = std::tuple>
203 
204  //----------------------------------------------------------------------------
234  template <template <typename T, typename...> class Extractor, typename Target, typename Tuple>
236 
238  template <template <typename T, typename...> class Extractor, typename Target, typename Tuple>
239  constexpr std::size_t index_of_extracted_type_v =
241 
245  template <typename Target, typename Tuple>
247 
249  template <typename Target, typename Tuple>
251 
252  //----------------------------------------------------------------------------
282  template <template <typename T, typename...> class Extractor, typename Target, typename Tuple>
284  std::tuple_element<index_of_extracted_type_v<Extractor, Target, Tuple>, Tuple>;
285 
287  template <template <typename T, typename...> class Extractor, typename Target, typename Tuple>
290 
291  //----------------------------------------------------------------------------
336  template <template <typename T, typename...> class Extractor, typename Target, typename Tuple>
338 
340  template <template <typename T, typename...> class Extractor, typename Target, typename Tuple>
342 
345  template <typename Target, typename Tuple>
347 
349  template <typename Target, typename Tuple>
351 
352  //----------------------------------------------------------------------------
389  template <template <typename T, typename...> class Extractor, typename Target, typename Tuple>
390  auto getByExtractedType(Tuple const& data) -> decltype(auto);
391 
416  template <template <typename T, typename...> class Extractor, typename Tuple>
418  : public details::has_duplicate_types_unwrapper<extract_to_tuple_type_t<Tuple, Extractor>> {};
419 
421  template <template <typename T, typename...> class Extractor, typename Tuple>
424 
428  template <typename Tuple>
430 
432  template <typename Tuple>
434 
464  template <template <typename T, typename...> class Extractor, typename Target, typename Tuple>
466 
468  template <template <typename T, typename...> class Extractor, typename Target, typename Tuple>
469  constexpr unsigned int count_extracted_types_v =
471 
475  template <typename Target, typename Tuple>
477 
479  template <typename Target, typename Tuple>
480  constexpr unsigned int count_types_v = count_types<Target, Tuple>();
481 
483 
531  template <typename T, typename Tag>
532  struct TaggedType : public T {
533 
534  // Forward all constructors
535  template <typename... Args>
536  TaggedType(Args&&... args) : T(std::forward<Args>(args)...)
537  {}
538 
539  using tag = Tag;
540  using tagged_type = T;
541 
542  }; // struct TaggedType
543 
546  template <typename T, typename Tag>
547  struct add_tag {
549  };
550 
553  template <typename T, typename Tag>
555 
557  template <typename Tagged>
558  struct remove_tag {
559  using type = Tagged;
560  };
561 
562  template <typename T, typename Tag>
563  struct remove_tag<TaggedType<T, Tag>> {
565  };
566 
568  template <typename Tagged>
570 
582  template <typename Tag, typename T>
583  auto makeTagged(T& obj) -> decltype(auto)
584  {
585  return static_cast<add_tag_t<T, Tag>&>(obj);
586  }
587 
599  template <typename Tag, typename T>
600  auto makeTagged(T const& obj) -> decltype(auto)
601  {
602  return static_cast<add_tag_t<T const, Tag> const&>(obj);
603  }
604 
617  template <typename Tag, typename T>
618  auto makeTagged(T const&& obj) -> decltype(auto)
619  {
620  return add_tag_t<T, Tag>(obj); /* copy, since it's constant */
621  }
622 
636  template <typename Tag, typename T>
637  auto makeTagged(T&& obj) -> decltype(auto)
638  {
639  return add_tag_t<T, Tag>(std::move(obj));
640  }
641 
643  template <typename Tagged>
644  auto removeTag(Tagged& tagged) -> decltype(auto)
645  {
646  return static_cast<remove_tag_t<Tagged>&>(tagged);
647  }
648 
650  template <typename Tagged>
651  auto removeTag(Tagged const& tagged) -> decltype(auto)
652  {
653  return static_cast<remove_tag_t<Tagged> const&>(tagged);
654  }
655 
657  template <typename Tagged>
658  auto removeTag(Tagged const&& tagged) -> decltype(auto)
659  {
660  return static_cast<remove_tag_t<Tagged> const&&>(tagged);
661  }
662 
664  template <typename Tagged>
665  auto removeTag(Tagged&& tagged) -> decltype(auto)
666  {
667  return static_cast<remove_tag_t<Tagged>&&>(tagged);
668  }
669 
671  template <std::size_t...>
672  struct TagN {};
673 
682  template <typename Tagged>
684 
686  template <typename Tagged>
688 
690  template <typename Tagged>
691  using tag_of_t = typename tag_of<Tagged>::type;
692 
694  template <typename SrcTuple>
696 
698  template <typename SrcTuple>
700 
731  template <typename Tag, typename Tuple>
733 
735  template <typename Tag, typename Tuple>
736  constexpr std::size_t index_of_tag_v = index_of_tag<Tag, Tuple>();
737 
767  template <typename Tag, typename Tuple>
769 
771  template <typename Tag, typename Tuple>
773 
798  template <typename Tag, typename Tuple>
800 
802  template <typename Tag, typename Tuple>
803  constexpr bool has_tag_v = has_tag<Tag, Tuple>();
804 
829  template <typename Tag, typename Tuple>
831 
833  template <typename Tag, typename Tuple>
834  constexpr unsigned int count_tags_v = count_tags<Tag, Tuple>();
835 
851  template <typename Tuple>
853 
855  template <typename Tuple>
857 
882  template <typename Tag, typename Tuple>
883  auto getByTag(Tuple const& data) -> decltype(auto)
884  {
885  return getByExtractedType<TagExtractor, Tag>(data);
886  }
887 
889 
890 } // namespace util
891 
892 //------------------------------------------------------------------------------
893 //--- Template implementation
894 //------------------------------------------------------------------------------
895 namespace util {
896 
897  namespace details {
898 
899  //--------------------------------------------------------------------------
900  //
901  // CAUTION: prolonged exposition to this code may result into loss of sight.
902  //
903  //--------------------------------------------------------------------------
904  //--- implementation details (most are not documented)
905  //--------------------------------------------------------------------------
906  //--- General utilities
907  //--------------------------------------------------------------------------
908  template <typename Target, typename... T>
909  struct count_type_in_list_impl : public std::integral_constant<unsigned int, 0U> {};
910 
911  template <typename Target, typename First, typename... Others>
912  struct count_type_in_list_impl<Target, First, Others...>
913  : public std::integral_constant<unsigned int,
914  count_type_in_list_impl<Target, Others...>::value> {};
915 
916  template <typename Target, typename... Others>
917  struct count_type_in_list_impl<Target, Target, Others...>
918  : public std::integral_constant<unsigned int,
919  count_type_in_list_impl<Target, Others...>::value + 1> {};
920 
921  //--------------------------------------------------------------------------
922  //--- Courtesy traits
923  //--------------------------------------------------------------------------
924 
925  //--------------------------------------------------------------------------
926  //--- Tagging
927  //--------------------------------------------------------------------------
928 
929  //--------------------------------------------------------------------------
930 
931  //--------------------------------------------------------------------------
932  template <typename Target, typename... T>
933  struct type_is_in_impl : public std::false_type {};
934 
935  template <typename Target, typename First, typename... Others>
936  struct type_is_in_impl<Target, First, Others...>
937  : public std::integral_constant<bool, type_is_in_impl<Target, Others...>::value> {};
938 
939  template <typename Target, typename... Others>
940  struct type_is_in_impl<Target, Target, Others...> : public std::true_type {};
941 
942  //--------------------------------------------------------------------------
961  template <template <typename...> class TargetClass,
962  template <typename T, typename...>
963  class Extractor,
964  typename Tuple,
965  std::size_t I,
966  std::size_t N,
967  typename... T>
969  using type = typename extract_to_tuple_type_impl<
970  TargetClass,
971  Extractor,
972  Tuple,
973  (I + 1),
974  N,
975  T...,
976  typename Extractor<std::tuple_element_t<I, Tuple>>::type>::type;
977  }; // extract_to_tuple_type_impl
978 
980  template <template <typename...> class TargetClass,
981  template <typename T, typename...>
982  class Extractor,
983  typename Tuple,
984  std::size_t N,
985  typename... T>
986  struct extract_to_tuple_type_impl<TargetClass, Extractor, Tuple, N, N, T...> {
987  using type = TargetClass<T...>;
988  }; // extract_to_tuple_type_impl<N>
989 
990  //--------------------------------------------------------------------------
991 
992  // TODO try alternative simple implementation:
993  template <typename SrcTuple,
994  template <typename T, typename...>
995  class Extractor,
996  template <typename...>
997  class TargetClass,
998  std::size_t... I>
1000  using type = TargetClass<typename Extractor<std::tuple_element_t<I, SrcTuple>>::type...>;
1001  }; // extract_to_tuple_type_impl<N>
1002 
1003  //--------------------------------------------------------------------------
1004 
1005  // Part of implementation for `index_of_extracted_type`.
1006  template <template <typename T, typename...> class Extractor,
1007  typename Target,
1008  std::size_t I,
1009  typename Elem,
1010  typename Tuple>
1012 
1013  // Part of implementation for `index_of_extracted_type`.
1014  template <template <typename T, typename...> class Extractor,
1015  typename Target,
1016  std::size_t N,
1017  std::size_t I,
1018  typename Tuple>
1021  Extractor,
1022  Target,
1023  I,
1024  typename Extractor<std::tuple_element_t<I, Tuple>>::type,
1025  Tuple> {};
1026 
1027  // Part of implementation for `index_of_extracted_type`.
1028  template <template <typename T, typename...> class Extractor,
1029  typename Target,
1030  std::size_t N,
1031  typename Tuple>
1032  struct index_of_extracted_type_checked<Extractor, Target, N, N, Tuple>
1033  : public std::integral_constant<std::size_t, N> {};
1034  template <template <typename T, typename...> class Extractor,
1035  typename Target,
1036  std::size_t I,
1037  typename Elem,
1038  typename Tuple>
1040  : public index_of_extracted_type_checked<Extractor,
1041  Target,
1042  std::tuple_size<Tuple>::value,
1043  (I + 1),
1044  Tuple> {};
1045 
1046  // Part of implementation for `index_of_extracted_type`.
1047  template <template <typename T, typename...> class Extractor,
1048  typename Target,
1049  std::size_t I,
1050  typename Tuple>
1051  struct index_of_extracted_type_impl<Extractor, Target, I, Target, Tuple>
1052  : public std::integral_constant<std::size_t, I> {
1053  static constexpr std::size_t N = std::tuple_size<Tuple>();
1054  static_assert(I < N, "Internal logic error.");
1055  };
1056 
1057  // Part of implementation for `index_of_extracted_type`.
1058  template <template <typename T, typename...> class Extractor,
1059  typename Target,
1060  std::size_t N,
1061  std::size_t After,
1062  typename Tuple>
1064  : public index_of_extracted_type_checked<Extractor, Target, N, (After + 1), Tuple> {};
1065 
1066  // Part of implementation for `index_of_extracted_type`.
1067  template <template <typename T, typename...> class Extractor,
1068  typename Target,
1069  std::size_t N,
1070  typename Tuple>
1071  struct index_of_extracted_type_checked_after<Extractor, Target, N, N, Tuple>
1072  : public std::integral_constant<std::size_t, N> {};
1073 
1074  // Part of implementation for `index_of_extracted_type`.
1075  // This implementation relies on std::tuple_size and std::tuple_element;
1076  // an implementation assuming Tuple to be std::tuple would be more efficient...
1077  template <template <typename T, typename...> class Extractor, typename Target, typename Tuple>
1079  : public std::integral_constant<std::size_t,
1080  index_of_extracted_type_checked<Extractor,
1081  Target,
1082  std::tuple_size<Tuple>::value,
1083  0U,
1084  Tuple>::value> {};
1085 
1086  // Part of implementation for `index_of_extracted_type`.
1087  template <template <typename T, typename...> class Extractor, typename Target, typename Tuple>
1089  static constexpr std::size_t N = std::tuple_size<Tuple>::value;
1090  static constexpr std::size_t value = index_of_type_base<Extractor, Target, Tuple>();
1091 
1092  static_assert(value < N, "The specified tuple does not have the sought type.");
1094  N,
1095  "The specified tuple has more than one element with the sought type.");
1096  }; // struct index_of_type_helper
1097 
1098  //--------------------------------------------------------------------------
1099  // Part of implementation of `has_duplicate_types`.
1100  template <typename Tuple, typename... T>
1101  struct has_duplicate_types_impl : public std::false_type {};
1102 
1103  template <typename Tuple, typename First, typename... Others>
1104  struct has_duplicate_types_impl<Tuple, First, Others...>
1105  : public std::integral_constant<bool,
1106  (count_type_in_tuple<First, Tuple>::value > 1U) ||
1107  has_duplicate_types_impl<Tuple, Others...>::value> {};
1108 
1109  // Part of implementation of `has_duplicate_types`.
1110  template <typename... T>
1111  struct has_duplicate_types_unwrapper<std::tuple<T...>>
1112  : public has_duplicate_types_impl<std::tuple<T...>, T...> {};
1113 
1114  //--------------------------------------------------------------------------
1115  // Part of implementation of `count_extracted_types` (might be exposed...).
1116  template <template <typename T, typename...> class Extractor, typename Target, typename... Tags>
1118  : public count_type_in_list<typename Extractor<Target>::type, Tags...> {};
1119 
1120  template <template <typename T, typename...> class Extractor,
1121  typename Target,
1122  typename... TagTuple>
1124 
1125  template <template <typename T, typename...> class Extractor, typename Target, typename... Tags>
1126  struct count_tags_in_tuple<Extractor, Target, std::tuple<Tags...>>
1127  : public count_type_in_tuple<typename Extractor<Target>::type, Tags...> {};
1128 
1129  //--------------------------------------------------------------------------
1130  //--- Tag traits
1131  //--------------------------------------------------------------------------
1132  template <typename Tagged, typename /* = void */>
1133  struct TagExtractorImpl {
1134  static_assert(always_false_type<Tagged>(), "This type is not tagged.");
1135  };
1136 
1137  template <typename Tagged>
1139  Tagged,
1140  std::enable_if_t<always_true_type<typename std::remove_reference_t<Tagged>::tag>::value>> {
1141  using type = typename std::remove_reference_t<Tagged>::tag;
1142  };
1143 
1144  //--------------------------------------------------------------------------
1145 
1146  } // namespace details
1147 
1148  //----------------------------------------------------------------------------
1149  //--- Implementation of the exposed traits
1150  //----------------------------------------------------------------------------
1151  //--- General utilities
1152  //----------------------------------------------------------------------------
1153  template <typename Target, typename Tuple>
1154  struct count_type_in_tuple {
1155  static_assert(always_false_type<Tuple>(),
1156  "count_type_in_tuple requires an instance of std::tuple");
1157  };
1158 
1159  // specialization: only works for std::tuples
1160  template <typename Target, typename... T>
1161  struct count_type_in_tuple<Target, std::tuple<T...>> : public count_type_in_list<Target, T...> {};
1162 
1163  //----------------------------------------------------------------------------
1164  //--- Courtesy traits
1165  //----------------------------------------------------------------------------
1166  template <typename SrcTuple,
1167  template <typename T, typename...>
1168  class Extractor,
1169  template <typename...>
1170  class TargetClass /* = std::tuple */
1171  >
1172  struct extract_to_tuple_type {
1173  private:
1174  static constexpr std::size_t N = std::tuple_size<SrcTuple>();
1175 
1176  public:
1177  using type =
1179  }; // extract_to_tuple_type
1180 
1181  //----------------------------------------------------------------------------
1182  template <template <typename T, typename...> class Extractor, typename Target, typename Tuple>
1184  : public std::integral_constant<
1185  std::size_t,
1186  details::index_of_type_helper<Extractor, Target, Tuple>::value> {};
1187 
1188  //----------------------------------------------------------------------------
1189  template <template <typename T, typename...> class Extractor, typename Target, typename Tuple>
1190  struct has_extracted_type
1191  : public std::integral_constant<bool,
1192  (details::index_of_type_base<Extractor, Target, Tuple>::value <
1193  std::tuple_size<Tuple>::value)> {};
1194 
1195  //----------------------------------------------------------------------------
1196  template <template <typename T, typename...> class Extractor, typename Target, typename Tuple>
1197  struct count_extracted_types
1198  : public count_type_in_tuple<Target, extract_to_tuple_type_t<Tuple, Extractor>> {};
1199 
1200  //----------------------------------------------------------------------------
1201  template <template <typename T, typename...> class Extractor, typename Target, typename Tuple>
1202  auto getByExtractedType(Tuple const& data) -> decltype(auto)
1203  {
1204  using std::get;
1205  return get<index_of_extracted_type_v<Extractor, Target, Tuple>>(data);
1206  }
1207 
1208  //----------------------------------------------------------------------------
1209  //--- Tagging utilities
1210  //----------------------------------------------------------------------------
1211 
1212  //----------------------------------------------------------------------------
1213 } // namespace util
1214 
1215 //------------------------------------------------------------------------------
1216 
1217 #endif // LARDATA_UTILITIES_TUPLELOOKUPBYTAG_H
TaggedType(Args &&...args)
Namespace for general, non-LArSoft-specific utilities.
Definition: PIDAAlg.h:26
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.
constexpr unsigned int count_tags_v
Direct access to the value in count_tags.
auto getByTag(Tuple const &data) -> decltype(auto)
Returns the object with the specified tag.
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 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:91
typename extract_to_tuple_type_impl< TargetClass, Extractor, Tuple,(I+1), N, T..., typename Extractor< std::tuple_element_t< I, Tuple >>::type >::type type
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 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.
TargetClass< typename Extractor< std::tuple_element_t< I, SrcTuple >>::type... > type
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.
auto makeTagged(T &obj) -> decltype(auto)
"Converts" obj to an object with tag Tag.
double value
Definition: spectrum.C:18
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...>.
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.
decltype(auto) get(T &&obj)
ADL-aware version of std::to_string.
Definition: StdUtils.h:120
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.
auto removeTag(Tagged &tagged) -> decltype(auto)
"Converts" a tagged type back to its original type.
Implementation for extract_to_tuple_type.
typename details::extract_to_tuple_type_impl< TargetClass, Extractor, SrcTuple, 0U, N >::type 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.