mirror of
https://github.com/espressif/openthread.git
synced 2026-07-29 23:27:46 +00:00
[common] enforce correct CRTP usage for mix-in classes (#11880)
The mix-in helper classes like `Clearable<T>`, `Equatable<T>`, and `Unequatable<T>` are intended for CRTP style inheritance, where `T` is the derived class itself. A mistaken inheritance, such as `class Foo : public Clearable<Bar>`, can compile successfully but lead to subtle bugs. This change enforces the correct CRTP usage at compile time. By making the constructors of these helper classes `private` and declaring the derived template class `T` as a `friend`, any incorrect inheritance will now result in a build failure. This approach correctly detects such a mistake, even if `Foo` and `Bar` happen to be `friend`s of each other. Additionally, `Equatable<T>` is updated to provide both `operator==` and `operator!=`, removing its dependency on `Unequatable<T>`. This change allows us to apply the `private` constructor enforcement to `Equatable<T>` as well.
This commit is contained in:
@@ -66,8 +66,13 @@ template <typename ObjectType> void ClearAllBytes(ObjectType &aObject)
|
||||
*/
|
||||
template <typename Type> class Clearable
|
||||
{
|
||||
friend Type;
|
||||
|
||||
public:
|
||||
void Clear(void) { ClearAllBytes<Type>(*static_cast<Type *>(this)); }
|
||||
|
||||
private:
|
||||
Clearable(void) = default;
|
||||
};
|
||||
|
||||
} // namespace ot
|
||||
|
||||
@@ -50,6 +50,8 @@ namespace ot {
|
||||
*/
|
||||
template <typename Type> class Unequatable
|
||||
{
|
||||
friend Type;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Overloads operator `!=` to evaluate whether or not two instances of `Type` are equal.
|
||||
@@ -62,6 +64,9 @@ public:
|
||||
* @retval FALSE If the two `Type` instances are equal.
|
||||
*/
|
||||
bool operator!=(const Type &aOther) const { return !(*static_cast<const Type *>(this) == aOther); }
|
||||
|
||||
private:
|
||||
Unequatable(void) = default;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -72,8 +77,10 @@ public:
|
||||
* Users of this class should follow CRTP-style inheritance, i.e., the `Type` class itself should publicly inherit
|
||||
* from `Equatable<Type>`.
|
||||
*/
|
||||
template <typename Type> class Equatable : public Unequatable<Type>
|
||||
template <typename Type> class Equatable
|
||||
{
|
||||
friend Type;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Overloads operator `==` to evaluate whether or not two instances of `Type` are equal.
|
||||
@@ -87,6 +94,19 @@ public:
|
||||
{
|
||||
return memcmp(static_cast<const Type *>(this), &aOther, sizeof(Type)) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloads operator `!=` to evaluate whether or not two instances of `Type` are equal.
|
||||
*
|
||||
* @param[in] aOther The other `Type` instance to compare with.
|
||||
*
|
||||
* @retval TRUE If the two `Type` instances are not equal.
|
||||
* @retval FALSE If the two `Type` instances are equal.
|
||||
*/
|
||||
bool operator!=(const Type &aOther) const { return !(*static_cast<const Type *>(this) == aOther); }
|
||||
|
||||
private:
|
||||
Equatable(void) = default;
|
||||
};
|
||||
|
||||
} // namespace ot
|
||||
|
||||
Reference in New Issue
Block a user