DUNE PDELab (git)

interface.hh
1#ifndef DUNE_PDELAB_BACKEND_INTERFACE_HH
2#define DUNE_PDELAB_BACKEND_INTERFACE_HH
3
4#include <type_traits>
5#include <utility>
6
7namespace Dune {
8 namespace PDELab {
9 namespace Backend {
10
11#ifndef DOXYGEN
12
13 namespace impl {
14
15 // This class needs to be specialized by each backend and return the correct
16 // vector wrapper type via the nested type named "type"
17 template<typename Backend, typename GridFunctionSpace, typename FieldType>
18 struct BackendVectorSelectorHelper
19 {};
20
21 template<typename GridFunctionSpace, typename FieldType>
22 struct BackendVectorSelector
23 {
24 typedef typename GridFunctionSpace::Traits::Backend Backend;
25 typedef typename BackendVectorSelectorHelper<Backend, GridFunctionSpace, FieldType>::Type Type;
26 };
27
28 template<typename Backend, typename VU, typename VV, typename E>
29 struct BackendMatrixSelector
30 {
31 typedef typename Backend::template MatrixHelper<VV,VU,E>::type Type;
32 };
33
34 // marker mixin type used by the generic implementation below to decide whether a type
35 // is a PDELab wrapper around a native object - for internal use only!
36 struct WrapperBase
37 {};
38
39 // mixin class for PDELab wrappers around vectors and matrices.
40 // All backend wrappers should inherit from this class and set the
41 // template parameter to the type of the native container of the backend that they are
42 // wrapping.
43 // Moreover, they have to provide methods
44 //
45 // NativeContainer& native()
46 // const NativeContainer& native() const
47 //
48 // that provide access to the wrapped data structure. These two methods should be private;
49 // in that case, the Wrapper<NativeContainer> mixin must be a friend of the wrapper implementation
50 // so that it can access the native() methods.
51 template<typename NativeContainer>
52 struct Wrapper
53 : public WrapperBase
54 {
55
56 using native_type = NativeContainer;
57
58 template<typename U>
59 static auto access_native(U&& u) -> decltype(u.native())
60 {
61 // make sure the wrapper actually returns the right type of object
62 static_assert(
63 std::is_same<
64 typename std::decay<
65 decltype(u.native())
66 >::type,
67 NativeContainer
68 >::value,
69 "u.native() must return a cv-qualified xvalue of type T"
70 );
71
72 return u.native();
73 }
74
75 };
76
77 } // namespace impl
78
79 } // namespace Backend
80
81
82 namespace Backend{
83
84#endif // DOXYGEN
85
86
105 template<typename GridFunctionSpace, typename FieldType>
106 using Vector = typename impl::BackendVectorSelector<GridFunctionSpace, FieldType>::Type;
107
126 template<typename Backend, typename VU, typename VV, typename E>
127 using Matrix = typename impl::BackendMatrixSelector<Backend, VU, VV, E>::Type;
128
129
130 namespace {
131
132 // helper TMP to deduce the native type of a wrapper. It works by checking whether
133 // T inherits from WrapperBase. In that case, it returns the nested typedef native_type,
134 // otherwise T is returned unchanged.
135 template<typename T>
136 struct native_type
137 {
138
139 // We need to defer the (possible) extraction of the nested type until we are sure
140 // that the nested type actually exists. That'w what these lazy_... structs are for:
141 // a std::conditional picks the correct version, and the actual evaluation only happens
142 // after the evaluation of the std::conditional.
143
144 struct lazy_identity
145 {
146 template<typename U>
147 struct evaluate
148 {
149 using type = U;
150 };
151
152 };
153
154 struct lazy_native_type
155 {
156
157 template<typename U>
158 struct evaluate
159 {
160 using type = typename U::native_type;
161 };
162
163 };
164
165 using type = typename std::conditional<
166 std::is_base_of<impl::WrapperBase,T>::value,
167 lazy_native_type,
168 lazy_identity
169 >::type::template evaluate<T>::type;
170 };
171
172 }
173
175 template<typename T>
176 using Native = typename native_type<T>::type;
177
178#ifdef DOXYEN
179
181 template<typename T>
182 Native<T> native(T&& t);
183
184#else // DOXYGEN
185
186 // version for mutable reference to wrapper
187 template<typename T>
188 typename std::enable_if<
189 std::is_base_of<impl::WrapperBase,T>::value,
190 Native<T>&
191 >::type
192 native(T& t)
193 {
194 return impl::Wrapper<Native<T>>::access_native(t);
195 }
196
197 // version for const reference to wrapper
198 template<typename T>
199 typename std::enable_if<
200 std::is_base_of<impl::WrapperBase,T>::value,
201 const Native<T>&
202 >::type
203 native(const T& t)
204 {
205 return impl::Wrapper<Native<T>>::access_native(t);
206 }
207
208 // version for non-wrapper class. Important: Don't drop the std::decay<>!
209 template<typename T>
210 typename std::enable_if<
211 !std::is_base_of<impl::WrapperBase,typename std::decay<T>::type>::value,
212 decltype(std::forward<T>(std::declval<T&&>()))
213 >::type
214 native(T&& t)
215 {
216 return std::forward<T>(t);
217 }
218
219#endif // DOXYGEN
220
221 } // namespace Backend
222 } // namespace PDELab
223} // namespace Dune
224
225#endif // DUNE_PDELAB_BACKEND_INTERFACE_HH
Dune namespace.
Definition: alignedallocator.hh:13
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 12, 23:30, 2024)