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