ensurePointer.h
Go to the documentation of this file.
1 #ifndef canvas_Utilities_ensurePointer_h
2 #define canvas_Utilities_ensurePointer_h
3 
4 // Ensure we can get a desired pointer type from a compatible iterator.
5 
6 // In order to allow new iterator value types (e.g. smart pointers) to
7 // be converted to pointers, specialize art::detail::EnsurePointer.
8 
9 // See canvas/Persistency/Common/Ptr.h for an example of this. Also see
10 // test/Utilities/ensurePointer.h for testing coverage illustration.
11 
13 #include "cetlib_except/demangle.h"
14 
15 #include <iterator>
16 #include <type_traits>
17 
18 namespace art {
19 
20  template <typename WANTED_POINTER, typename InputIterator>
21  WANTED_POINTER ensurePointer(InputIterator it);
22 
23  namespace detail {
24  template <typename T1, typename T2>
26  using T1P = std::remove_cv_t<std::remove_pointer_t<T1>>;
27  using T2P = std::remove_cv_t<std::remove_pointer_t<T2>>;
28  static constexpr bool value{std::is_base_of_v<T1P, T2P> ||
29  std::is_same_v<T1P, T2P>};
30  };
31 
32  template <typename TO, typename FROM>
34  std::add_pointer_t<std::remove_pointer_t<TO>>>
35  addr(FROM& from)
36  {
37  return &from;
38  }
39 
40  template <typename TO, typename FROM>
43  std::add_pointer_t<std::remove_pointer_t<TO>>>
44  addr(FROM& from)
45  {
46  return &dynamic_cast<
47  std::add_lvalue_reference_t<std::remove_pointer_t<TO>>>(from);
48  }
49 
50  template <typename TO, typename FROM>
51  struct EnsurePointer {
52  constexpr TO
53  operator()(FROM& from) const
54  {
55  return addr<TO>(from);
56  }
57  constexpr TO
58  operator()(FROM const& from) const
59  {
60  return addr<TO>(from);
61  }
62  };
63 
64  template <typename TO, typename PFROM>
65  struct EnsurePointer<TO, PFROM*> {
66  constexpr TO
67  operator()(PFROM* from) const
68  {
69  return addr<TO>(*from);
70  }
71  };
72  }
73 }
74 
75 template <typename WANTED_POINTER, typename InputIterator>
76 inline WANTED_POINTER
77 art::ensurePointer(InputIterator it) try {
78  static_assert(std::is_pointer_v<WANTED_POINTER>,
79  "Supplied template argument is not a pointer.");
80  return detail::EnsurePointer<
81  WANTED_POINTER,
82  typename std::iterator_traits<InputIterator>::value_type>{}(*it);
83 }
84 catch (std::bad_cast&) {
85  throw Exception(errors::LogicError, "ensurePointer")
86  << "Iterator value type "
87  << cet::demangle_symbol(
88  typeid(typename std::iterator_traits<InputIterator>::value_type)
89  .name())
90  << " and wanted pointer type "
91  << cet::demangle_symbol(typeid(WANTED_POINTER).name())
92  << " are incompatible.\n";
93 }
94 #endif /* canvas_Utilities_ensurePointer_h */
95 
96 // Local Variables:
97 // mode: c++
98 // End:
static QCString name
Definition: declinfo.cpp:673
std::remove_cv_t< std::remove_pointer_t< T1 >> T1P
Definition: ensurePointer.h:26
constexpr TO operator()(FROM const &from) const
Definition: ensurePointer.h:58
std::remove_cv_t< std::remove_pointer_t< T2 >> T2P
Definition: ensurePointer.h:27
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
constexpr TO operator()(PFROM *from) const
Definition: ensurePointer.h:67
static constexpr bool value
Definition: ensurePointer.h:28
constexpr TO operator()(FROM &from) const
Definition: ensurePointer.h:53
constexpr std::enable_if_t< are_cv_compatible< TO, FROM >::value, std::add_pointer_t< std::remove_pointer_t< TO > > > addr(FROM &from)
Definition: ensurePointer.h:35
WANTED_POINTER ensurePointer(InputIterator it)
Definition: ensurePointer.h:77