LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
MetaUtils.h
Go to the documentation of this file.
1 
23 #ifndef LARCOREALG_COREUTILS_METAUTILS_H
24 #define LARCOREALG_COREUTILS_METAUTILS_H
25 
26 // C/C++ standard libraries
27 #include <array>
28 #include <functional> // std::reference_wrapper<>
29 #include <memory> // std::addressof()
30 #include <string>
31 #include <string_view>
32 #include <type_traits>
33 
39 namespace util {
40 
41  //--- BEGIN MetaprogrammingBase ----------------------------------------------
47 
49  namespace details {
50 
52  template <typename T>
54 
55  } // namespace details
56 
57  //----------------------------------------------------------------------------
59  template <typename T>
60  struct self_type {
61  using type = T;
62  };
63 
65  template <typename T>
66  using self_t = typename self_type<T>::type;
67 
68  //----------------------------------------------------------------------------
90  template <typename>
91  struct always_false_type : public std::false_type {};
92 
93  //----------------------------------------------------------------------------
114  template <typename>
115  constexpr bool always_false_v = false;
116 
139  template <typename>
140  struct always_true_type : public std::true_type {};
141 
161  template <typename>
162  constexpr bool always_true_v = true;
163 
165  template <typename A, typename B>
166  using is_not_same = std::negation<std::is_same<A, B>>;
167 
168  //----------------------------------------------------------------------------
188  template <typename T, std::size_t StartFrom, typename... Types>
190 
191  template <typename T, std::size_t StartFrom, typename... Types>
192  constexpr std::size_t find_next_type_v = find_next_type<T, StartFrom, Types...>::value;
193 
194  //----------------------------------------------------------------------------
211  template <typename T, typename... Types>
212  using find_type = find_next_type<T, 0U, Types...>;
213 
216  template <typename T, typename... Types>
217  constexpr std::size_t find_type_v = find_type<T, Types...>::value;
218 
219  //----------------------------------------------------------------------------
229  template <typename T, typename... Types>
230  struct is_any_of;
231 
233  template <typename T, typename... Types>
234  constexpr bool is_any_of_v = is_any_of<T, Types...>::value;
235 
236  //----------------------------------------------------------------------------
238  template <typename T, typename U>
239  constexpr auto is_same_decay_v = std::is_same_v<std::decay_t<T>, std::decay_t<U>>;
240 
241  //----------------------------------------------------------------------------
242  // @{
298  template <typename T>
299  void staticDumpClassName();
300 
301  template <typename T>
303  {
304  staticDumpClassName<T>();
305  }
306  // @}
307 
309  //--- END MetaprogrammingBase ------------------------------------------------
310 
311  //--- BEGIN Type identification ----------------------------------------------
317 
319  //----------------------------------------------------------------------------
320 
344  template <template <typename...> typename Template, typename T>
346 
349  template <template <typename...> typename Template, typename T>
351 
352  //----------------------------------------------------------------------------
358  template <typename T>
359  struct is_STLarray;
360 
366  template <typename T>
368 
369  //----------------------------------------------------------------------------
375  template <typename T>
377 
384  template <typename T>
386 
387  //----------------------------------------------------------------------------
393  template <typename T>
395 
402  template <typename T>
404 
405  //----------------------------------------------------------------------------
414  template <typename T>
416 
418  template <typename T>
420 
421  //----------------------------------------------------------------------------
432  template <typename T>
434 
436  template <typename T>
438 
439  //----------------------------------------------------------------------------
447  template <typename T>
449 
452  template <typename T>
454 
455  //----------------------------------------------------------------------------
463  template <typename T>
465 
468  template <typename T>
470 
472  //--- END Type identification ------------------------------------------------
473 
474  //--- BEGIN Type manipulation ------------------------------------------------
480 
482  //----------------------------------------------------------------------------
505  template <typename Base, typename Key>
507 
514  template <typename Base, typename Key>
516 
517  //----------------------------------------------------------------------------
530  template <typename T>
532 
538  template <typename T>
540 
541  //----------------------------------------------------------------------------
552  template <typename Ref>
553  auto referenced_address(Ref&& ref);
554 
555  //----------------------------------------------------------------------------
573  template <typename Ref>
574  decltype(auto) operator()(Ref&& ref) const
575  {
576  return addressof(std::forward<Ref>(ref));
577  }
578 
579  template <typename Ref>
580  static decltype(auto) addressof(Ref&& ref)
581  {
582  return referenced_address(std::forward<Ref>(ref));
583  }
584 
585  }; // struct reference_addresser
586 
587  //----------------------------------------------------------------------------
601  template <typename T>
603 
609  template <typename T>
611 
623  template <typename T>
625  {
627  }
628 
629  //----------------------------------------------------------------------------
630 
632  //--- END Type manipulation --------------------------------------------------
633 
634 } // namespace util
635 
636 //------------------------------------------------------------------------------
637 //--- Template implementation
638 //------------------------------------------------------------------------------
639 namespace util {
640 
641  //----------------------------------------------------------------------------
642  namespace details {
643 
644  //--------------------------------------------------------------------------
645  template <std::size_t Index, std::size_t Skip, typename T, typename... Types>
647 
648  template <std::size_t Index, std::size_t Skip, typename T, typename Type, typename... Others>
649  struct find_type_impl<Index, Skip, T, Type, Others...>
650  : std::integral_constant<
651  std::size_t,
652  (Skip == 0) && std::is_same_v<T, Type> ?
653  Index :
654  find_type_impl<Index + 1U, ((Skip > 0U) ? Skip - 1U : 0U), T, Others...>::value> {};
655 
656  template <std::size_t Index, std::size_t Skip, typename T>
657  struct find_type_impl<Index, Skip, T> : std::integral_constant<std::size_t, Index> {};
658 
659  //--------------------------------------------------------------------------
660  template <typename T, typename = void>
662  : std::bool_constant<util::is_any_of_v<std::decay_t<T>,
663  signed char,
664  unsigned char,
665  char,
666  wchar_t,
667 #ifdef __cpp_char8_t // C++20
668  char8_t,
669 #endif // __cpp_char8_t
670  char16_t, // this is defined unsigned
671  char32_t // this is defined unsigned
672  >> {
673  };
674 
675  //--------------------------------------------------------------------------
676  template <typename T, typename = void>
677  struct is_string_type_impl : std::false_type {};
678 
679  template <typename T>
681  T,
682  std::enable_if_t<is_character_type_impl<typename T::value_type>::value>> : std::true_type {};
683 
684  template <typename T>
686  T,
687  std::enable_if_t<std::is_pointer_v<std::decay_t<T>> &&
688  is_character_type_impl<std::remove_pointer_t<std::decay_t<T>>>::value>>
689  : std::true_type {};
690 
691  template <typename T>
693  T,
694  std::enable_if_t<std::is_array_v<std::decay_t<T>> &&
695  is_character_type_impl<std::remove_extent_t<std::decay_t<T>>>::value>>
696  : std::true_type {};
697 
698  //--------------------------------------------------------------------------
699  template <typename T>
700  struct is_basic_string_type_impl : std::false_type {};
701 
702  template <typename... Args>
703  struct is_basic_string_type_impl<std::basic_string<Args...>> : std::true_type {};
704 
705  //--------------------------------------------------------------------------
706  template <typename T>
707  struct is_basic_string_view_type_impl : std::false_type {};
708 
709  template <typename... Args>
710  struct is_basic_string_view_type_impl<std::basic_string_view<Args...>> : std::true_type {};
711 
712  //--------------------------------------------------------------------------
714  template <typename T>
715  struct ClassNameStaticDumper {
716  static_assert(util::always_false_type<T>(),
717  "ClassNameStaticDumper<T>: look for T in the error message context");
718  }; // struct ClassNameStaticDumper
719 
720  //--------------------------------------------------------------------------
721  // implementation for `with_const_as`
722 
723  // - final implementation:
724  template <typename Base, typename /* Key */, typename = void>
726  using type = std::remove_const_t<Base>;
727  };
728 
729  template <typename Base, typename Key>
730  struct with_const_as_impl<Base, Key, std::enable_if_t<std::is_const_v<Key>>> {
731  using type = std::add_const_t<Base>;
732  };
733 
734  // - implementation dispatcher for reference types
735  // - pass through for not-reference types
736  template <typename Base, typename Key, typename = void>
738  // - lvalue reference
739  template <typename Base, typename Key>
741  Key,
742  std::enable_if_t<std::is_lvalue_reference_v<Base>>> {
743  using type = std::add_lvalue_reference_t<
745  };
746  // - rvalue reference
747  template <typename Base, typename Key>
749  Key,
750  std::enable_if_t<std::is_rvalue_reference_v<Base>>> {
751  using type = std::add_rvalue_reference_t<
753  };
754 
755  // - key management
756  template <typename Base, typename Key>
758  : with_const_as_dispatch_ref<Base, std::remove_reference_t<Key>> {};
759 
760  // - top level implementation dispatcher
761  template <typename Base, typename Key>
763 
764  //--------------------------------------------------------------------------
765  //--- implementation of `is_instance_of`
766  template <template <typename...> typename Template, typename T>
767  struct is_instance_of_impl : std::false_type {};
768 
769  template <template <typename...> typename Template, typename... Args>
770  struct is_instance_of_impl<Template, Template<Args...>> : std::true_type {};
771 
772  //--------------------------------------------------------------------------
773  //--- implementation of `strip_referenceness_type`
774 
775  template <typename T>
777 
778  // implementation layer dealing with `std::reference_wrapper`
779  template <typename T, typename = void>
781  using type = T;
782  }; // exit here
783 
784  // - handle any constantness and volatility
785  template <typename T>
787  T,
788  std::enable_if_t<util::is_reference_wrapper_v<std::remove_cv_t<T>>>>
789  : strip_referenceness_type_impl<typename T::type> // back to square one
790  {};
791 
792  // implementation layer dealing with C++ references
793  template <typename T>
795 
796  template <typename T>
798 
799  template <typename T>
801 
802  // entry point: start by dealing with C++ references
803  template <typename T>
805 
806  //--------------------------------------------------------------------------
807  //--- implementation of `referenced_address()`
808 
809  template <typename T, typename = void>
811  static auto addressof(T& obj) { return std::addressof(obj); }
812  };
813 
814  template <typename T>
815  struct referenced_address_impl<T, std::enable_if_t<util::is_reference_wrapper_v<T>>> {
816  static auto addressof(T& obj) { return std::addressof(obj.get()); }
817  };
818 
819  //--------------------------------------------------------------------------
820  //--- implementation of `lvalue_reference_into_wrapper_type`
821  /*
822  * The implementation develops across levels:
823  * 1. any kind of `std::reference_wrapper` is handled
824  * 2. l-value references are handled
825  */
826  template <typename T>
828  using type = std::remove_reference_t<T>;
829  };
830 
831  template <typename T>
833  using type = std::reference_wrapper<T>;
834  };
835 
836  template <typename T, typename = void>
839  };
840 
841  template <typename T>
843  T,
844  std::enable_if_t<util::is_reference_wrapper_v<T>>> {
845  using type = std::remove_reference_t<T>;
846  };
847 
848  template <typename T>
851 
852  //--------------------------------------------------------------------------
853 
854  } // namespace details
855 
856  //----------------------------------------------------------------------------
857  template <template <typename...> typename Template, typename T>
858  struct is_instance_of : details::is_instance_of_impl<Template, std::decay_t<T>> {};
859 
860  //----------------------------------------------------------------------------
861  template <typename T, std::size_t StartFrom, typename... Types>
862  struct find_next_type : details::find_type_impl<0U, StartFrom, T, Types...> {};
863 
864  //----------------------------------------------------------------------------
865  template <typename T, typename... Types>
866  struct is_any_of : std::bool_constant<((find_type_v<T, Types...>) < sizeof...(Types))> {};
867 
868  //----------------------------------------------------------------------------
869  template <typename T>
870  struct is_character_type : details::is_character_type_impl<T> {};
871 
872  //----------------------------------------------------------------------------
873  template <typename T>
874  struct is_string_type : details::is_string_type_impl<T> {};
875 
876  //----------------------------------------------------------------------------
877  template <typename T>
878  struct is_basic_string_type : details::is_basic_string_type_impl<std::decay_t<T>> {};
879 
880  //----------------------------------------------------------------------------
881  template <typename T>
882  struct is_basic_string_view_type : details::is_basic_string_view_type_impl<std::decay_t<T>> {};
883 
884  //----------------------------------------------------------------------------
885  template <typename T>
886  void staticDumpClassName()
887  {
888  (void)details::ClassNameStaticDumper<T>();
889  }
890 
891  //----------------------------------------------------------------------------
892  template <typename>
893  struct is_STLarray : public std::false_type {};
894 
895  template <typename T, std::size_t N>
896  struct is_STLarray<std::array<T, N>> : public std::true_type {};
897 
898  //----------------------------------------------------------------------------
899  template <typename Base, typename Key>
900  struct with_const_as : public details::with_const_as_dispatcher<Base, Key> {};
901 
902  //----------------------------------------------------------------------------
903  template <typename T>
904  struct strip_referenceness_type : public details::strip_referenceness_type_impl<T> {};
905 
906  //----------------------------------------------------------------------------
907  template <typename T>
908  struct lvalue_reference_into_wrapper_type
909  : public details::lvalue_reference_into_wrapper_type_impl<T> {};
910 
911  //----------------------------------------------------------------------------
912  template <typename Ref>
913  auto referenced_address(Ref&& ref)
914  {
915  return details::referenced_address_impl<Ref>::addressof(ref);
916  }
917 
918  //----------------------------------------------------------------------------
919 
920 } // namespace util
921 
922 //------------------------------------------------------------------------------
923 
924 #endif // LARCOREALG_COREUTILS_METAUTILS_H
constexpr bool is_string_type_v
Whether type T is a character string type (see util::is_string_type).
Definition: MetaUtils.h:437
Implementation detail of staticDumpClassName().
Definition: MetaUtils.h:53
typename strip_referenceness_type< T >::type strip_referenceness_t
The type T stripped of all known reference types.
Definition: MetaUtils.h:539
Namespace for general, non-LArSoft-specific utilities.
Definition: PIDAAlg.h:26
Functor applying the proper referenced_address() function.
Definition: MetaUtils.h:572
constexpr bool always_true_v
A template constant always true.
Definition: MetaUtils.h:162
std::add_rvalue_reference_t< typename with_const_as_impl< std::remove_reference_t< Base >, Key >::type > type
Definition: MetaUtils.h:752
Identifies whether the specified type is a STL array.
Definition: MetaUtils.h:359
constexpr auto is_same_decay_v
Whether T and U are the same type, after being applied std::decay.
Definition: MetaUtils.h:239
constexpr bool is_basic_string_type_v
Definition: MetaUtils.h:453
typename lvalue_reference_into_wrapper_type_impl_final< T >::type type
Definition: MetaUtils.h:838
constexpr std::size_t find_next_type_v
Definition: MetaUtils.h:192
STL namespace.
typename with_const_as< Base, Key >::type with_const_as_t
The type Base, plus the constantness as in Key.
Definition: MetaUtils.h:515
std::integral_constant< bool, Value > bool_constant
Definition: ProviderPack.h:298
Trait with type Base, plus the constantness as in Key.
Definition: MetaUtils.h:506
typename self_type< T >::type self_t
The very same type as in the template argument.
Definition: MetaUtils.h:66
A std::false_type with a template argument.
Definition: MetaUtils.h:91
constexpr bool is_reference_wrapper_v
A constant describing whether the specified type is a std::reference_wrapper.
Definition: MetaUtils.h:385
std::add_lvalue_reference_t< typename with_const_as_impl< std::remove_reference_t< Base >, Key >::type > type
Definition: MetaUtils.h:744
Trait: whether type T is a character string type.
Definition: MetaUtils.h:433
std::negation< std::is_same< A, B >> is_not_same
The negation of std::is_same.
Definition: MetaUtils.h:166
Trait: whether type T is a character type.
Definition: MetaUtils.h:415
Trait returning the very same type as in the template argument.
Definition: MetaUtils.h:60
constexpr bool always_false_v
A templated constant, always false.
Definition: MetaUtils.h:115
constexpr bool is_basic_string_view_type_v
Definition: MetaUtils.h:469
constexpr bool is_unique_ptr_v
A constant describing whether the specified type is a std::unique_ptr.
Definition: MetaUtils.h:403
constexpr bool is_character_type_v
Whether type T is a character type (see util::is_character_type).
Definition: MetaUtils.h:419
double value
Definition: spectrum.C:18
A std::true_type with a template argument.
Definition: MetaUtils.h:140
void staticDumpClassName()
Helper to determine the type of a variable at compilation time.
Definition: MetaUtils.h:886
auto lvalue_reference_into_wrapper(T &&obj)
Converts a l-value reference object into a std::reference_wrapper.
Definition: MetaUtils.h:624
Trait with type T stripped of all known reference types.
Definition: MetaUtils.h:531
Trait: index of the first occurrence of T among the specified Types, starting from the one with index...
Definition: MetaUtils.h:189
constexpr std::size_t find_type_v
Definition: MetaUtils.h:217
Trait describing whether T is a template instance of Template.
Definition: MetaUtils.h:345
constexpr bool is_any_of_v
Whether T is among the specified Types (see util::is_any_of).
Definition: MetaUtils.h:234
Trait: whether type T is a STL string type.
Definition: MetaUtils.h:448
Trait: whether T is among the specified Types.
Definition: MetaUtils.h:230
Trait with type T into std::reference_wrapper if reference.
Definition: MetaUtils.h:602
Trait: whether type T is a std::string_view type.
Definition: MetaUtils.h:464
auto referenced_address(Ref &&ref)
Returns the address of the referenced object.
Definition: MetaUtils.h:913
constexpr bool is_STLarray_v
A constant describing whether the specified type is a STL array.
Definition: MetaUtils.h:367
typename lvalue_reference_into_wrapper_type< T >::type lvalue_reference_into_wrapper_t
The type T stripped of all known reference types.
Definition: MetaUtils.h:610
constexpr bool is_instance_of_v
Definition: MetaUtils.h:350