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