Phi
to_address.hpp
1 #ifndef PHI_CORE_TO_ADDRESS_HPP
2 #define PHI_CORE_TO_ADDRESS_HPP
3 
4 #include "phi/phi_config.hpp"
5 
6 #if PHI_HAS_EXTENSION_PRAGMA_ONCE()
7 # pragma once
8 #endif
9 
10 #include "phi/compiler_support/constexpr.hpp"
11 #include "phi/compiler_support/noexcept.hpp"
12 #include "phi/core/declval.hpp"
13 #include "phi/core/pointer_traits.hpp"
14 #include "phi/type_traits/conjunction.hpp"
15 #include "phi/type_traits/decay.hpp"
16 #include "phi/type_traits/enable_if.hpp"
17 #include "phi/type_traits/is_class.hpp"
18 #include "phi/type_traits/is_function.hpp"
19 
20 DETAIL_PHI_BEGIN_NAMESPACE()
21 
22 namespace detail
23 {
24  template <typename TypeT>
25  PHI_CONSTEXPR TypeT* to_address_impl(TypeT* pointer) PHI_NOEXCEPT
26  {
27  static_assert(is_not_function<TypeT>::value,
28  "phi::detail::to_address_impl: TypeT must not be a function type");
29  return pointer;
30  }
31 
32  template <typename PointerT, typename = void>
33  struct has_to_address : public false_type
34  {};
35 
36  template <typename PointerT>
37  struct has_to_address<PointerT, decltype((void)pointer_traits<PointerT>::to_address(
38  declval<const PointerT&>()))> : public true_type
39  {};
40 
41  template <typename PointerT, typename = void>
43  {};
44 
45  template <typename PointerT>
46  struct pointer_has_operator_arrow<PointerT,
47  decltype((void)declval<const PointerT&>().operator->())>
48  : public true_type
49  {};
50 
51  template <typename PointerT>
53  {
54  static PHI_CONSTEXPR_AND_CONST bool value =
56  };
57 
58  template <typename PointerT, typename = void>
60 
61  // enable_if is needed here to avoid instantiating checks for fancy pointers on raw pointers
62  template <typename PointerT, typename = enable_if_t<conjunction<
63  is_class<PointerT>, is_fancy_pointer<PointerT>>::value>>
64  PHI_CONSTEXPR decay_t<
65  decltype(to_address_impl_helper<PointerT>::call(declval<const PointerT&>()))>
66  to_address_impl(const PointerT& pointer) PHI_NOEXCEPT
67  {
69  }
70 
71  template <typename PointerT, typename>
73  {
74  static PHI_CONSTEXPR decltype(to_address_impl(declval<const PointerT&>().operator->()))
75  call(const PointerT& pointer) PHI_NOEXCEPT
76  {
77  return to_address_impl(pointer.operator->());
78  }
79  };
80 
81  template <typename PointerT>
82  struct to_address_impl_helper<PointerT, decltype((void)pointer_traits<PointerT>::to_address(
83  declval<const PointerT&>()))>
84  {
85  static PHI_CONSTEXPR decltype(pointer_traits<PointerT>::to_address(
86  declval<const PointerT&>()))
87  call(const PointerT& pointer) PHI_NOEXCEPT
88  {
90  }
91  };
92 } // namespace detail
93 
94 template <typename TypeT>
95 PHI_CONSTEXPR auto to_address(TypeT* pointer) PHI_NOEXCEPT
96 {
97  return detail::to_address_impl(pointer);
98 }
99 
100 template <typename PointerT>
101 PHI_CONSTEXPR auto to_address(const PointerT& pointer) PHI_NOEXCEPT
102  -> decltype(detail::to_address_impl(pointer))
103 {
104  return detail::to_address_impl(pointer);
105 }
106 
107 DETAIL_PHI_END_NAMESPACE()
108 
109 #endif // PHI_CORE_TO_ADDRESS_HPP
Definition: integral_constant.hpp:19
Definition: to_address.hpp:59
Definition: is_function.hpp:50
Definition: swap.hpp:23
Definition: to_address.hpp:33
Definition: to_address.hpp:42
Definition: pointer_traits.hpp:109
Definition: to_address.hpp:52