Suppose that we want to change the name of the property OldProperty to NewProperty. In order to stay backwards compatible, a user should be able to use both the new name and the old name. If he uses the old name, he should get a deprecation warning, but his code should still do the same as before.
The only working possibility is to have two properties OldProperty and NewProperty and to set by default the new one to the old one. The other way around, a user could only invoke OldProperty in his using declarations if he doesn't specialize NewProperty in his own code.
Actions to be done in the module <tt>dumux</tt> before release
Deprecate the old property
template<class TypeTag, class MyTypeTag>
struct [[deprecated("Use OldProperty instead.")]] OldProperty { using type = UndefinedProperty; };
using type = typename NewPropertyHelper<TypeTag, typename OldProperty<TypeTag, MyTypeTag>::type>::type;
};
#pragma GCC diagnostic pop
The ignore pragmas avoid the emission of deprecation warnings for using the old property inside. The indirection via the helper class is required to allow specializing the new property with an undefined/unspecialized old one.
Specializations still have to be performed in terms of the old property, otherwise user code can't employ the old name. Only the ignore pragmas have to be added.
Use the new name
Change all
using MyOldFavoriteName = GetPropType<TypeTag, Properties::OldProperty>;
to
using MyNewFavoriteName = GetPropType<TypeTag, Properties::NewProperty>;
Export the new name
Very often, MyOldFavoriteName in the snippet above coincides with OldProperty. In this case, it is advisable to set MyNewFavoriteName to NewProperty. While this is unproblematic if the alias is local, take special care for exported names:
public:
using OldProperty = GetPropType<TypeTag, Properties::OldProperty>;
should become
public:
using NewProperty = GetPropType<TypeTag, Properties::NewProperty>;
using OldProperty [[deprecated("Use NewProperty instead.")]] = NewProperty;
Actions to be done in derived modules and user code
Change using declarations
Change all
using MyOldFavoriteName = GetPropType<TypeTag, Properties::OldProperty>;
to
using MyNewFavoriteName = GetPropType<TypeTag, Properties::NewProperty>;
If MyOldFavoriteName is exported and you care about backwards compatibility, consider deprecating it as outlined above.
Treat specializations
Change all
struct OldProperty<TypeTag, TTag::SpecialModel> {
using type = SpecialType<...>;
};
to
struct NewProperty<TypeTag, TTag::SpecialModel> {
using type = SpecialType<...>;
};
This should work because everywhere we now get the new property, so it is possible to overwrite it without breaking the code.
Actions to be done in the module <tt>dumux</tt> after release
Only define the new property
Replace the two snippets "Deprecate the old property" and "Define the new property" by
template<class TypeTag, class MyTypeTag>
struct NewProperty { using type = UndefinedProperty; };
Only specialize the new property
Replace the dumux code base snippet "Treat specializations" by
struct NewProperty<TypeTag, TTag::SpecialModel> {
using type = SpecialType<...>;
};
Remove exports of the old name
Remove the line containing the deprecation from the snippet "Export the new name".
Known limitation
Unfortunately, clang emits false positives when invoking the outlined strategy. A workaround is to prevent clang from emitting deprecation warnings triggered by using GetPropType and getPropValue(). To this end, the line