Add utilities for std::reference_wrapper
This adds the following helpers for handling std::reference_wrapper
:
- A predicate
IsReferenceWrapper_v<R>
for detecting ifR
is astd::reference_wrapper<T>
. - A helper function
resolveRef
for resolving references wrapped instd::reference_wrapper
. For typeT
providing a methodT::foo()
this allows to transparently useresolveRef(t).foo()
ift
is either a plainT
or astd::reference_wrapper<T>
. - A type alias
ResolveRef_t<T>
to determine the resolved type forT
.
Merge request reports
Activity
added feature label
The utilities can be used to implement the following pattern for function concepts
C
with extended interface (e.g.GridFunction
):Assume that a downstream class should work with (and capture) a function
f
implementing the extended function interfaceC
. Then it can follow the standard pattern to capturef
by value. To explicitly capture by reference users can passstd::ref(f)
. For the internally stored valuef_
extended methodsC::foo()
can be called usingresolveRef(f_).foo()
.mentioned in merge request !316 (merged)
added 3 commits
-
af405a95...9a44a0ec - 2 commits from branch
master
- af831466 - Add utilities for std::reference_wrapper
-
af405a95...9a44a0ec - 2 commits from branch
I also had this in mind. But since the pattern to store copies by default and provide reference support using
std::reference_wrapper
is mostly advertised for callbacks, I thought that we can test this approach here first. (However, I'd very much appreciate if theVTKWriter
would also follow this pattern. Maybe, if someone ever does a clean re-implementation of a vtk writer, he can keep this in mind ;-))
- dune/functions/common/referencehelper.hh 0 → 100644
43 */ 44 template<class T, std::enable_if_t<not IsReferenceWrapper_v<T>, int> = 0> 45 auto& resolveRef(T& gf) 46 { 47 return gf; 48 } 49 50 /** 51 * \brief Helper function to resolve std::reference_wrapper 52 * 53 * This is the overload for plain const l-value reference types. 54 * It simply forwards the passed const l-value reference. 55 * 56 * \ingroup Utility 57 */ 58 template<class T, std::enable_if_t<not IsReferenceWrapper_v<T>, int> = 0> changed this line in version 3 of the diff
In fact the check was necessary to support
const reference_wrapper<T>&
andreference_wrapper<T>&&
. But this is now treated more clearly by writing these overloads explicitly. This also adds proper treatment of r-values:reference_wrapper<T>&&
is OK, but the overload for plainT&&
is deleted to prevent nasal demons. Furthermore all cases are now checked in a new test.
- dune/functions/common/referencehelper.hh 0 → 100644
68 { 69 return gf.get(); 70 } 71 72 73 /** 74 * \brief Helper function to resolve std::reference_wrapper 75 * 76 * This is the overload for const std::reference_wrapper<T>. 77 * It resolves the reference by returning the stored 78 * (mutable or const) l-value reference. 79 * 80 * \ingroup Utility 81 */ 82 template<class T> 83 auto& resolveRef(const std::reference_wrapper<T>& gf) One could even go one step further an replace all the overloads with different const/ref qualifiern of
std::reference_wrapper
with just one function without reference:template<class T> auto& resolveRef(std::reference_wrapper<T> gf) { return gf.get(); }
It has precedence over the other non-reference_wrapper overloads and handles all three cases at once. The reference_wrapper can be copied without copying the underlying wrapped element.
changed this line in version 5 of the diff
You're right, and the copy should not harm since
std::reference_wrapper
is trivially copyable. I implemented the change. Notice that the deleted overload forT&&
is also not needed but is deliberately kept for documentation purpose and to get nicer compile errors. I also addedconstexpr
andnoexcept
in the new version.
mentioned in commit d74194c9
mentioned in merge request core/dune-common!1100 (merged)