dune-pdelab  2.4.1
concept.hh
Go to the documentation of this file.
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 #ifndef DUNE_PDELAB_COMMON_CONCEPT_HH
4 #define DUNE_PDELAB_COMMON_CONCEPT_HH
5 
6 #include <type_traits>
7 #include <utility>
8 #include <tuple>
9 
12 
13 
14 
15 namespace Dune {
16 namespace PDELab {
17 
18 
19 // Forward declaration
20 template<class C, class... T>
21 constexpr bool models();
22 
23 
24 
32 namespace Concept {
33 
34 
35 
48 template<class... BaseConcepts>
49 struct Refines
50 {
51  typedef TypeList<BaseConcepts...> BaseConceptList;
52 };
53 
54 
55 
56 namespace Imp {
57 
58  // #############################################################################
59  // # All functions following here are implementation details
60  // # for the models() function below.
61  // #############################################################################
62 
63  // Here is the implementation of the concept checking.
64  // The first two overloads do the magic for checking
65  // if the requirements of a concept are satisfied.
66  // The rest is just for checking base concepts in case
67  // of refinement.
68 
69  // This overload is present if type substitution for
70  // C::require(T...) is successful, i.e., if the T...
71  // matches the requirement of C. In this case this
72  // overload is selected because PriorityTag<1>
73  // is a better match for PrioriryTag<42> than
74  // PriorityTag<0> in the default overload.
75  template<class C, class... T,
76  decltype(std::declval<C>().require(std::declval<T>()...), 0) =0>
77  constexpr std::true_type matchesRequirement(PriorityTag<1>)
78  { return {}; }
79 
80  // If the above overload is ruled out by SFINAE because
81  // the T... does not match the requirements of C, then
82  // this default overload drops in.
83  template<class C, class... T>
84  constexpr std::false_type matchesRequirement(PriorityTag<0>)
85  { return {}; }
86 
87 
88 
89  // An empty list C of concepts is always matched by T...
90  template<class...T>
91  constexpr bool modelsConceptList(TypeList<>)
92  { return true; }
93 
94  // A nonempty list C0,..,CN of concepts is modeled
95  // by T... if it models the concept C0
96  // and all concepts in the list C1,..,CN.
97  template<class...T, class C0, class... CC>
99  { return models<C0, T...>() and modelsConceptList<T...>(TypeList<CC...>()); }
100 
101 
102 
103  // If C is an unrefined concept, then T... models C
104  // if it matches the requirement of C.
105  template<class C, class... T>
107  { return matchesRequirement<C, T...>(PriorityTag<42>()); }
108 
109  // If C is a refined concept, then T... models C
110  // if it matches the requirement of C and of
111  // all base concepts.
112  //
113  // This overload is used if C::BaseConceptList exists
114  // due to its higher priority.
115  template<class C, class... T,
116  decltype(typename C::BaseConceptList(), 0) = 0>
118  { return matchesRequirement<C, T...>(PriorityTag<42>()) and modelsConceptList<T...>(typename C::BaseConceptList()); }
119 
120 
121 
122  // #############################################################################
123  // # All functions following here are implementation details for the
124  // # for the tupleEntriesModel() function below.
125  // #############################################################################
126 
127  template<class C, class First>
128  constexpr auto allModel()
129  -> std::integral_constant<bool, models<C, First>()>
130  { return {}; }
131 
132  template<class C, class First, class... Other>
133  constexpr auto allModel()
134  -> std::integral_constant<bool, models<C, First>() and allModel<C, Other...>()>
135  { return {}; }
136 
137  template<class C, class... T>
138  constexpr auto tupleEntriesModel(const std::tuple<T...>&)
139  -> decltype(allModel<C, T...>())
140  { return {}; }
141 
142 } // namespace Dune::Concept::Imp
143 
144 
145 
146 // #############################################################################
147 // # The method tupleEntriesModel() does the actual check if the types in a tuple
148 // # model a concept using the implementation details above.
149 // #############################################################################
150 
151 template<class C, class Tuple>
152 constexpr auto tupleEntriesModel()
153  -> decltype(Imp::tupleEntriesModel<C>(std::declval<Tuple>()))
154 {
155  return {};
156 }
157 
158 // #############################################################################
159 // # The following require*() functions are just helpers that allow to
160 // # propagate a failed check as substitution failure. This is usefull
161 // # inside of a concept definition.
162 // #############################################################################
163 
164 // Helper function for use in concept definitions.
165 // If the passed value b is not true, the concept will to be satisfied.
166 template<bool b, typename std::enable_if<b, int>::type = 0>
167 constexpr bool requireTrue()
168 {
169  return true;
170 }
171 
172 // Helper function for use in concept definitions.
173 template<class C, class... T, typename std::enable_if<models<C, T...>(), int>::type = 0>
174 constexpr bool requireConcept()
175 {
176  return true;
177 }
178 
179 // Helper function for use in concept definitions.
180 // This allows to avoid using decltype
181 template<class C, class... T, typename std::enable_if<models<C, T...>(), int>::type = 0>
182 constexpr bool requireConcept(T&&... t)
183 {
184  return true;
185 }
186 
187 // Helper function for use in concept definitions.
188 // This checks if the concept given as first type is modelled by all types in the tuple passed as argument
189 template<class C, class Tuple, typename std::enable_if<tupleEntriesModel<C, Tuple>(), int>::type = 0>
191 {
192  return true;
193 }
194 
195 // Helper function for use in concept definitions.
196 // If the first passed type is not convertible to the second, the concept will not be satisfied.
197 template<class From, class To,
199 constexpr bool requireConvertible()
200 {
201  return true;
202 }
203 
204 // Helper function for use in concept definitions.
205 // If passed argument is not convertible to the first passed type, the concept will not be satisfied.
206 template<class To, class From,
207  typename std::enable_if< std::is_convertible<From, To>::value, int>::type = 0>
208 constexpr bool requireConvertible(const From&)
209 {
210  return true;
211 }
212 
213 // Helper function for use in concept definitions.
214 // This will always evaluate to true. If just allow
215 // to turn a type into an expression. The failure happens
216 // already during substitution for the type argument.
217 template<typename T>
218 constexpr bool requireType()
219 {
220  return true;
221 }
222 
223 // Helper function for use in concept definitions.
224 // If first passed type is not a base class of second type, the concept will not be satisfied.
225 template<class Base, class Derived,
227 constexpr bool requireBaseOf()
228 {
229  return true;
230 }
231 
232 // Helper function for use in concept definitions.
233 // If first passed type is not a base class of first arguments type, the concept will not be satisfied.
234 template<class Base, class Derived,
235  typename std::enable_if< std::is_base_of<Base, Derived>::value, int>::type = 0>
236 constexpr bool requireBaseOf(const Derived&)
237 {
238  return true;
239 }
240 
241 // Helper function for use in concept definitions.
242 // If the passed types are not the same, the concept will not be satisfied.
243 template<class A, class B,
244  typename std::enable_if< std::is_same<A, B>::value, int>::type = 0>
245 constexpr bool requireSameType()
246 {
247  return true;
248 }
249 
250 
251 
252 } // namespace Dune::Concept
253 
254 
255 
281 template<class C, class... T>
282 constexpr bool models()
283 {
284  return Concept::Imp::modelsConcept<C, T...>(PriorityTag<42>());
285 }
286 
287 
288 
289 } // namespace PDELab
290 } // namespace Dune
291 
292 
293 
294 
295 #endif // DUNE_PDELAB_COMMON_CONCEPT_HH
constexpr bool modelsConceptList(TypeList< C0, CC... >)
Definition: concept.hh:98
constexpr bool modelsConcept(PriorityTag< 0 >)
Definition: concept.hh:106
constexpr auto allModel() -> std::integral_constant< bool, models< C, First >() and allModel< C, Other... >()>
Definition: concept.hh:133
static const unsigned int value
Definition: gridfunctionspace/tags.hh:177
Helper class for tagging priorities.
Definition: typeutilities.hh:60
Definition: adaptivity.hh:27
constexpr bool requireConceptForTupleEntries()
Definition: concept.hh:190
constexpr bool modelsConcept(PriorityTag< 1 >)
Definition: concept.hh:117
constexpr auto tupleEntriesModel() -> decltype(Imp::tupleEntriesModel< C >(std::declval< Tuple >()))
Definition: concept.hh:152
TypeList< BaseConcepts... > BaseConceptList
Definition: concept.hh:51
constexpr bool requireSameType()
Definition: concept.hh:245
constexpr bool requireType()
Definition: concept.hh:218
Base class for refined concepts.
Definition: concept.hh:49
constexpr std::false_type matchesRequirement(PriorityTag< 0 >)
Definition: concept.hh:84
constexpr bool requireConvertible()
Definition: concept.hh:199
Utilities for type computations, constarining overloads, ...
constexpr bool requireConcept()
Definition: concept.hh:174
A simple type list.
Definition: typelist.hh:31
constexpr bool models()
Check if concept is modeled by given types.
Definition: concept.hh:282
constexpr bool requireTrue()
Definition: concept.hh:167
Helper class for tagging priorities.
Definition: typeutilities.hh:72
constexpr bool requireBaseOf()
Definition: concept.hh:227