Flexible compile-time parameters
A default value may be used if the user does not provide one at run-time
Can be used e.g. as template parameters (types or
values with constexpr
specifier); No run-time penalty,
enable compiler to optimize
An example - std::vector
// Declaration of the class template, usable with any
// `T` that fulfills the requirements that `vector` poses on it.
template<typename T, typename A = std::allocator<T>>
class vector;
// Instantiation of a concrete vector - a vector of ints.
// The compiler will define this concrete type for us,
// using the definition of the class template.
std::vector<int> v;
An example - std::vector
Template implementations can be specialized for concrete types
For some classes, providing all template parameters can be very cumbersome and error-prone.
A usual way to group template parameters
Inheritance may lead to unexpected results
Based on template specialization
// Type trait template declaration
template<typename T> struct ValueType;
// Specialization for vectors of T
template<typename T, typename Allocator>
struct ValueType<std::vector<T, Allocator>> { using type = T; };
// Specialization for Dune::FieldVector
template<typename T, int size>
struct ValueType<Dune::FieldVector<T, size>> { using type = T; };
A usage example
A simplified example to illustrate the idea
// myproperties.hh
namespace Dumux::Properties {
namespace TTag { struct MyTypeTag {}; }
// some property tag
template<typename TypeTag> struct PropTagA;
// property definition for MyTypeTag
template<>
struct PropTagA<MyTypeTag>
{ using type = /*the actual property*/; };
} // namespace Dumux::Properties
A simplified example to illustrate the idea
Issue: Inheritance not (easily) possible. All type
traits need to be specialized for MyTypeTag
.
Goal: We would like type tags to be composable via inheritance, while providing a mechanism for customizing any property defined in the hierarchy.
Let’s implement the Vector
example using the property
system
namespace Properties {
namespace TTag { struct BaseTag {}; }
// specialization of the Scalar property for BaseTag
template<class TypeTag>
struct Scalar<TypeTag, TTag::BaseTag> { using type = int; };
// specialization of the Vector property for BaseTag
template<class TypeTag>
struct Vector<TypeTag, TTag::BaseTag> {
private: using Scalar = GetPropType<TypeTag, Properties::Scalar>;
public: using type = std::vector<Scalar>;
};
Let’s implement the Vector
example using the property
system
Creating new TypeTag nodes
Creating new property tags (empty, unset properties) \(\leftrightarrow\) Property names are unique!
Usually not needed in user code because all necessary properties are already defined in dumux/common/properties.hh.
Setting type properties for a specific type tag
MyTypeTag
Alternatively, using type alias properties for a
specific type tag MyTypeTag
Setting value properties for a specific type tag
MyTypeTag
Setting value for a alias property for a specific
type tag MyTypeTag
Getting the property type set for a TypeTag