Line data Source code
1 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 :
13 : #include "Utilities/ForceInline.hpp"
14 : #include "Utilities/Math.hpp"
15 : #include "Utilities/Requires.hpp"
16 : #include "Utilities/TypeTraits/IsA.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 1 : decltype(auto) dereference_wrapper(T&& t) {
23 : return std::forward<T>(t);
24 : }
25 :
26 : /// \cond
27 : template <typename T>
28 : T& dereference_wrapper(const std::reference_wrapper<T>& t) {
29 : return t.get();
30 : }
31 : template <typename T>
32 : T& dereference_wrapper(std::reference_wrapper<T>& t) {
33 : return t.get();
34 : }
35 : template <typename T>
36 : T&& dereference_wrapper(const std::reference_wrapper<T>&& t) {
37 : return t.get();
38 : }
39 : template <typename T>
40 : T&& dereference_wrapper(std::reference_wrapper<T>&& 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 : // blaze vector types 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) { \
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) { \
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) { \
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) { \
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) { \
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) { \
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) { \
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) {
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
|