DereferenceWrapper.hpp
Go to the documentation of this file.
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 /// \file
5 /// Defines function dereference_wrapper
6 
7 #pragma once
8 
9 #include <complex>
10 #include <functional>
11 #include <utility>
12 
14 #include "Utilities/Math.hpp"
15 #include "Utilities/Requires.hpp"
16 #include "Utilities/TypeTraits.hpp"
17 
18 /// \ingroup UtilitiesGroup
19 /// \brief Returns the reference object held by a reference wrapper, if a
20 /// non-reference_wrapper type is passed in then the object is returned
21 template <typename T>
22 decltype(auto) dereference_wrapper(T&& t) {
23  return std::forward<T>(t);
24 }
25 
26 /// \cond
27 template <typename T>
29  return t.get();
30 }
31 template <typename T>
33  return t.get();
34 }
35 template <typename T>
37  return t.get();
38 }
39 template <typename T>
41  return t.get();
42 }
43 /// \endcond
44 
45 /// \cond
46 // Add overloads of math functions for reference_wrapper.
47 // This is necessary because if a class, say DataVector, inherits from
48 // PointerVector and does not specify the math operators specifically for
49 // DataVector then the implicit cast from reference_wrapper<DataVector> to
50 // DataVector does not result in finding the math operators.
51 //
52 // We use forwarding references to resolve ambiguity errors with
53 // DVecScalarMultExpr and DVecScalarDivExpr, with a std::reference_wrapper
54 // The forwarding references match everything perfectly and so the functions
55 // here will (almost) always win in overload selection.
56 #define UNARY_REF_WRAP_OP(OP) \
57  template <typename T> \
58  SPECTRE_ALWAYS_INLINE decltype(auto) OP( \
59  const std::reference_wrapper<T>& t) noexcept { \
60  return OP(t.get()); \
61  }
62 #define BINARY_REF_WRAP_FUNCTION_OP(OP) \
63  template < \
64  typename T0, typename T1, \
65  Requires<not tt::is_a_v<std::reference_wrapper, std::decay_t<T1>>> = \
66  nullptr> \
67  SPECTRE_ALWAYS_INLINE decltype(auto) OP( \
68  const std::reference_wrapper<T0>& t0, T1&& t1) noexcept { \
69  return OP(t0.get(), t1); \
70  } \
71  template < \
72  typename T0, typename T1, \
73  Requires<not tt::is_a_v<std::reference_wrapper, std::decay_t<T0>>> = \
74  nullptr> \
75  SPECTRE_ALWAYS_INLINE decltype(auto) OP( \
76  T0&& t0, const std::reference_wrapper<T1>& t1) noexcept { \
77  return OP(t0, t1.get()); \
78  } \
79  template <typename T0, typename T1> \
80  SPECTRE_ALWAYS_INLINE decltype(auto) OP( \
81  const std::reference_wrapper<T0>& t0, \
82  const std::reference_wrapper<T1>& t1) noexcept { \
83  return OP(t0.get(), t1.get()); \
84  }
85 
86 #define BINARY_REF_WRAP_OP(OP) \
87  template < \
88  typename T0, typename T1, \
89  Requires<not tt::is_a_v<std::reference_wrapper, std::decay_t<T1>>> = \
90  nullptr> \
91  SPECTRE_ALWAYS_INLINE decltype(auto) operator OP( \
92  const std::reference_wrapper<T0>& t0, T1&& t1) noexcept { \
93  return t0.get() OP t1; \
94  } \
95  template < \
96  typename T0, typename T1, \
97  Requires<not tt::is_a_v<std::reference_wrapper, std::decay_t<T0>>> = \
98  nullptr> \
99  SPECTRE_ALWAYS_INLINE decltype(auto) operator OP( \
100  T0&& t0, const std::reference_wrapper<T1>& t1) noexcept { \
101  return t0 OP t1.get(); \
102  } \
103  template <typename T0, typename T1> \
104  SPECTRE_ALWAYS_INLINE decltype(auto) operator OP( \
105  const std::reference_wrapper<T0>& t0, \
106  const std::reference_wrapper<T1>& t1) noexcept { \
107  return t0.get() OP t1.get(); \
108  }
109 
110 UNARY_REF_WRAP_OP(abs)
111 UNARY_REF_WRAP_OP(acos)
112 UNARY_REF_WRAP_OP(acosh)
113 UNARY_REF_WRAP_OP(asin)
114 UNARY_REF_WRAP_OP(asinh)
115 UNARY_REF_WRAP_OP(atan)
116 BINARY_REF_WRAP_FUNCTION_OP(atan2)
117 UNARY_REF_WRAP_OP(atanh)
118 UNARY_REF_WRAP_OP(cbrt)
119 UNARY_REF_WRAP_OP(conj)
120 UNARY_REF_WRAP_OP(cos)
121 UNARY_REF_WRAP_OP(cosh)
122 UNARY_REF_WRAP_OP(erf)
123 UNARY_REF_WRAP_OP(erfc)
124 UNARY_REF_WRAP_OP(exp)
125 UNARY_REF_WRAP_OP(exp2)
126 UNARY_REF_WRAP_OP(exp10)
127 UNARY_REF_WRAP_OP(fabs)
128 BINARY_REF_WRAP_FUNCTION_OP(hypot)
129 UNARY_REF_WRAP_OP(imag)
130 UNARY_REF_WRAP_OP(invcbrt)
131 UNARY_REF_WRAP_OP(invsqrt)
132 UNARY_REF_WRAP_OP(log)
133 UNARY_REF_WRAP_OP(log2)
134 UNARY_REF_WRAP_OP(log10)
135 UNARY_REF_WRAP_OP(max)
136 UNARY_REF_WRAP_OP(min)
137 BINARY_REF_WRAP_FUNCTION_OP(pow)
138 UNARY_REF_WRAP_OP(real)
139 UNARY_REF_WRAP_OP(sin)
140 UNARY_REF_WRAP_OP(sinh)
141 UNARY_REF_WRAP_OP(sqrt)
142 UNARY_REF_WRAP_OP(step_function)
143 UNARY_REF_WRAP_OP(tan)
144 UNARY_REF_WRAP_OP(tanh)
145 
146 BINARY_REF_WRAP_OP(+)
147 BINARY_REF_WRAP_OP(-)
148 BINARY_REF_WRAP_OP(*)
149 BINARY_REF_WRAP_OP(/)
150 BINARY_REF_WRAP_OP(==)
151 
152 template <typename T>
153 SPECTRE_ALWAYS_INLINE decltype(auto) operator-(
154  const std::reference_wrapper<T>& t) noexcept {
155  return -t.get();
156 }
157 
158 #undef UNARY_REF_WRAP_OP
159 #undef BINARY_REF_WRAP_OP
160 #undef BINARY_REF_WRAP_FUNCTION_OP
161 /// \endcond
constexpr T step_function(const T &arg) noexcept
Defines the Heaviside step function for arithmetic types. .
Definition: Math.hpp:62
auto invsqrt(const T &arg) noexcept
Defines the inverse square-root ( ) for arithmetic and complex types.
Definition: Math.hpp:71
Defines the type alias Requires.
#define SPECTRE_ALWAYS_INLINE
Always inline a function. Only use this if you benchmarked the code.
Definition: ForceInline.hpp:20
Defines macro to always inline a function.
auto invcbrt(const T &arg) noexcept
Defines the inverse cube-root ( ) for arithmetic types.
Definition: Math.hpp:79
decltype(auto) dereference_wrapper(T &&t)
Returns the reference object held by a reference wrapper, if a non-reference_wrapper type is passed i...
Definition: DereferenceWrapper.hpp:22
Defines type traits, some of which are future STL type_traits header.
decltype(auto) constexpr pow(const T &t) noexcept
Compute t^N where N is an integer (positive or negative)
Definition: ConstantExpressions.hpp:157