version 3.10-dev
propertysystem.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3//
4// SPDX-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
14#ifndef DUMUX_PROPERTY_SYSTEM_HH
15#define DUMUX_PROPERTY_SYSTEM_HH
16
17#include <tuple>
18#include <type_traits>
19#include <dune/common/std/type_traits.hh>
20
21namespace Dumux::Properties {
22
28
33template<class P> struct PropertyAlias;
34
35} // end namespace Dumux::Properties
36
37
38// hide from doxygen
39#ifndef DOXYGEN
40
42namespace Dumux::Properties::Detail {
43
45template<class P>
46constexpr auto isDefinedProperty(int)
47-> decltype(std::integral_constant<bool, !std::is_same_v<typename P::type, UndefinedProperty>>{})
48{ return {}; }
49
51template<class P>
52constexpr std::true_type isDefinedProperty(...) { return {}; }
53
55template<class T>
56constexpr auto hasParentTypeTag(int)
57-> decltype(std::declval<typename T::InheritsFrom>(), std::true_type{})
58{ return {}; }
59
61template<class T>
62constexpr std::false_type hasParentTypeTag(...)
63{ return {}; }
64
65
67template<class P, class T>
68using TypeAliasPropertyDetector = typename PropertyAlias<P>::template Alias<T>;
69
72template<class P, class T>
73struct TypeAliasProperty
74{ using type = Dune::Std::detected_or_t<UndefinedProperty, TypeAliasPropertyDetector, P, T>; };
75
77template<class P, class T, class TypeTag>
78using TemplateAliasPropertyDetector = typename PropertyAlias<P>::template TemplateAlias<T, TypeTag>;
79
82template<class P, class T, class TypeTag>
83struct TemplateAliasProperty
84{ using type = Dune::Std::detected_or_t<UndefinedProperty, TemplateAliasPropertyDetector, P, T, TypeTag>; };
85
86
88template<class T>
89using ValueMemberDetector = decltype(T::value);
90
92template<class T, bool hasValueMember = Dune::Std::is_detected_v<ValueMemberDetector, T>>
93struct ValueMember { static constexpr bool value = false; };
94
96template<class T>
97struct ValueMember<T, true> { static constexpr auto value = T::value; };
98
100template<class PropertySpecialization>
101struct GetPropValue { static constexpr auto value = ValueMember<PropertySpecialization>::value; };
102
104template<class P, class T>
105struct GetPropValue<TypeAliasProperty<P, T>>
106{ static constexpr auto value = ValueMember<typename TypeAliasProperty<P, T>::type>::value; };
107
109template<class P, class T, class TypeTag>
110struct GetPropValue<TemplateAliasProperty<P, T, TypeTag>>
111{ static constexpr auto value = ValueMember<typename TemplateAliasProperty<P, T, TypeTag>::type>::value; };
112
113
115template<class ...Tuples>
116using ConCatTuples = decltype(std::tuple_cat(std::declval<Tuples>()...));
117
119template<class TypeTag, template<class,class> class Property, class TTagList>
120struct GetDefined;
121
123template<class TypeTag, template<class,class> class Property, class TTagList, class Enable>
124struct GetNextTypeTag;
125
126template<class TypeTag, template<class,class> class Property, class LastTypeTag>
127struct GetNextTypeTag<TypeTag, Property, std::tuple<LastTypeTag>, std::enable_if_t<hasParentTypeTag<LastTypeTag>(int{}), void>>
128{ using type = typename GetDefined<TypeTag, Property, typename LastTypeTag::InheritsFrom>::type; };
129
130template<class TypeTag, template<class,class> class Property, class LastTypeTag>
131struct GetNextTypeTag<TypeTag, Property, std::tuple<LastTypeTag>, std::enable_if_t<!hasParentTypeTag<LastTypeTag>(int{}), void>>
132{ using type = UndefinedProperty; };
133
134template<class TypeTag, template<class,class> class Property, class FirstTypeTag, class ...Args>
135struct GetNextTypeTag<TypeTag, Property, std::tuple<FirstTypeTag, Args...>, std::enable_if_t<hasParentTypeTag<FirstTypeTag>(int{}), void>>
136{ using type = typename GetDefined<TypeTag, Property, ConCatTuples<typename FirstTypeTag::InheritsFrom, std::tuple<Args...>>>::type; };
137
138template<class TypeTag, template<class,class> class Property, class FirstTypeTag, class ...Args>
139struct GetNextTypeTag<TypeTag, Property, std::tuple<FirstTypeTag, Args...>, std::enable_if_t<!hasParentTypeTag<FirstTypeTag>(int{}), void>>
140{ using type = typename GetDefined<TypeTag, Property, std::tuple<Args...>>::type; };
141
142template<class TypeTag, template<class,class> class Property, class LastTypeTag>
143struct GetDefined<TypeTag, Property, std::tuple<LastTypeTag>>
144{
145// For clang, the following alias triggers compiler warnings if instantiated
146// from something like `GetPropType<..., DeprecatedProperty>`, even if that is
147// contained in a diagnostic pragma construct that should prevent these warnings.
148// As a workaround, also add the pragmas around this line.
149// See the discussion in MR 1647 for more details.
150#ifdef __clang__
151#pragma clang diagnostic push
152#pragma clang diagnostic ignored "-Wdeprecated-declarations"
153#endif
154 using LastType = Property<TypeTag, LastTypeTag>;
155#ifdef __clang__
156#pragma clang diagnostic pop
157#endif
158 using DirectType = TypeAliasProperty<LastType, LastTypeTag>;
159 using DirectTemplateType = TemplateAliasProperty<LastType, LastTypeTag, TypeTag>;
160 // See below for an explanation of this
161 using type = std::conditional_t<
162 isDefinedProperty<LastType>(int{}), LastType,
163 std::conditional_t<
164 isDefinedProperty<DirectTemplateType>(int{}), DirectTemplateType,
165 std::conditional_t<
166 isDefinedProperty<DirectType>(int{}), DirectType,
167 typename GetNextTypeTag<TypeTag, Property, std::tuple<LastTypeTag>, void>::type
168 >
169 >
170 >;
171};
172
173template<class TypeTag, template<class,class> class Property, class FirstTypeTag, class ...Args>
174struct GetDefined<TypeTag, Property, std::tuple<FirstTypeTag, Args...>>
175{
176// See the comment above.
177#ifdef __clang__
178#pragma clang diagnostic push
179#pragma clang diagnostic ignored "-Wdeprecated-declarations"
180#endif
181 using FirstType = Property<TypeTag, FirstTypeTag>;
182#ifdef __clang__
183#pragma clang diagnostic pop
184#endif
185 using DirectType = TypeAliasProperty<FirstType, FirstTypeTag>;
186 using DirectTemplateType = TemplateAliasProperty<FirstType, FirstTypeTag, TypeTag>;
187 // First we check if the property is specialized for the current type tag
188 // If yes, we found the correct specialization, if no we keep searching.
189 // Second, we check if the type tag contains an alias with the property name.
190 // If yes, we found the correct specialization, if no we keep searching.
191 // Third, we check if the type tag contains a template alias with the property name (template argument is TypeTag)
192 // If yes, we found the correct specialization, if no we the property is undefined (default definition)
193 using type = std::conditional_t<
194 isDefinedProperty<FirstType>(int{}), FirstType,
195 std::conditional_t<
196 isDefinedProperty<DirectTemplateType>(int{}), DirectTemplateType,
197 std::conditional_t<
198 isDefinedProperty<DirectType>(int{}), DirectType,
199 typename GetNextTypeTag<TypeTag, Property, std::tuple<FirstTypeTag, Args...>, void>::type
200 >
201 >
202 >;
203};
204
206template<class TypeTag, template<class,class> class Property>
207struct GetPropImpl
208{
209 using type = typename Detail::GetDefined<TypeTag, Property, std::tuple<TypeTag>>::type;
210 static_assert(!std::is_same_v<type, UndefinedProperty>, "Property is undefined!");
211};
212
213template<class TypeTag, template<class,class> class Property, class T>
214struct GetPropOrImpl
215{
216 using PT = typename Detail::GetDefined<TypeTag, Property, std::tuple<TypeTag>>::type;
217 struct WrapperT { using type = T; }; // fake property wrapper
218 using type = std::conditional_t<std::is_same_v<PT, UndefinedProperty>, WrapperT, PT>;
219};
220
221template<class ParentTag, class TypeTag, bool hasParents = hasParentTypeTag<TypeTag>(int{})>
222struct InheritsFrom;
223
224template<class ParentTag, class TypeTag>
225struct InheritsFrom<ParentTag, TypeTag, false> {
226 static constexpr bool value = std::is_same_v<ParentTag, TypeTag>;
227};
228
229template<class ParentTag, class TypeTag>
230struct InheritsFrom<ParentTag, TypeTag, true> {
231 static constexpr bool value = std::is_same_v<ParentTag, TypeTag>
232 || InheritsFrom<ParentTag, typename TypeTag::InheritsFrom, false>::value;
233};
234
235template<class ParentTag, class... TypeTags>
236struct InheritsFrom<ParentTag, std::tuple<TypeTags...>, false> {
237 static constexpr bool value = (InheritsFrom<ParentTag, TypeTags>::value || ...);
238};
239
240} // end namespace Dumux::Properties::Detail
241
242#endif // DOXYGEN
243
244namespace Dumux::Properties {
245
250template<class TypeTag, template<class,class> class Property>
251inline constexpr bool hasDefinedType()
252{
253 using type = typename Detail::GetDefined<TypeTag, Property, std::tuple<TypeTag>>::type;
254 return !std::is_same_v<type, UndefinedProperty>;
255}
256
261template<class ParentTypeTag, class TypeTag>
262inline constexpr bool inheritsFrom()
263{
264 return Detail::InheritsFrom<ParentTypeTag, TypeTag>::value;
265}
266
267} // end namespace Dumux::Properties
268
269namespace Dumux {
270
275template<class TypeTag, template<class,class> class Property>
276using GetProp = typename Properties::Detail::GetPropImpl<TypeTag, Property>::type;
277
282template<class TypeTag, template<class,class> class Property, class T>
283using GetPropOr = typename Properties::Detail::GetPropOrImpl<TypeTag, Property, T>::type;
284
285// See the comment above.
286#ifdef __clang__
287#pragma clang diagnostic push
288#pragma clang diagnostic ignored "-Wdeprecated-declarations"
289#endif
290
295template<class TypeTag, template<class,class> class Property>
297
302template<class TypeTag, template<class,class> class Property, class T>
304
309template<class TypeTag, template<class,class> class Property>
310inline constexpr auto getPropValue() { return Properties::Detail::GetPropValue<GetProp<TypeTag, Property>>::value; }
311#ifdef __clang__
312#pragma clang diagnostic pop
313#endif
314
315} // end namespace Dumux
316
349#define DUMUX_DEFINE_PROPERTY(Prop) \
350 template<class TypeTag, class MyTypeTag> \
351 struct Prop { \
352 using type = UndefinedProperty; \
353 }; \
354 template<class ...Args> \
355 struct PropertyAlias<Prop<Args...>> { \
356 template <class MyTypeTag> using Alias = typename MyTypeTag::Prop; \
357 template <class MyTypeTag, class TypeTag> using TemplateAlias = typename MyTypeTag::template Prop<TypeTag>; \
358 };
359
360#endif
constexpr auto getPropValue()
get the value data member of a property
Definition: propertysystem.hh:310
constexpr bool hasDefinedType()
whether the property is defined/specialized for TypeTag
Definition: propertysystem.hh:251
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type GetProp
get the type of a property
Definition: propertysystem.hh:276
typename Properties::Detail::GetPropOrImpl< TypeTag, Property, T >::type GetPropOr
get the type of a property or the type T if the property is undefined
Definition: propertysystem.hh:283
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:296
typename GetPropOr< TypeTag, Property, T >::type GetPropTypeOr
get the type alias defined in the property or the type T if the property is undefined
Definition: propertysystem.hh:303
constexpr bool inheritsFrom()
Return true if the given type tag inherits from the given parent type tag.
Definition: propertysystem.hh:262
The energy balance equation for a porous solid.
Definition: common/properties.hh:26
Definition: adapt.hh:17
a tag to specify a direct alias for property extraction
Definition: propertysystem.hh:33
a tag to mark properties as undefined
Definition: propertysystem.hh:27