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