From 92d52243afaa01262ccabd6b359793b9ae26cff4 Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Tue, 16 Nov 2021 15:17:12 +0100 Subject: [PATCH] ENH: support cref() and shallow copies (refPtr and tmp) - enables building HashTables with shadowed variables - support good() and valid() as synonyms in memory classes --- applications/test/refPtr/Test-refPtr.C | 18 ++++++--- applications/test/tmp/Test-tmp.C | 20 +++++++--- .../Field/PrecisionAdaptor/PrecisionAdaptor.H | 6 +-- src/OpenFOAM/memory/autoPtr/autoPtr.H | 11 +++++- src/OpenFOAM/memory/refPtr/refPtr.H | 32 ++++++++++++++-- src/OpenFOAM/memory/refPtr/refPtrI.H | 37 +++++++++++++++++-- src/OpenFOAM/memory/tmp/tmp.H | 36 ++++++++++++++---- src/OpenFOAM/memory/tmp/tmpI.H | 20 +++++++++- 8 files changed, 148 insertions(+), 32 deletions(-) diff --git a/applications/test/refPtr/Test-refPtr.C b/applications/test/refPtr/Test-refPtr.C index b2594d186c3..823fdb71680 100644 --- a/applications/test/refPtr/Test-refPtr.C +++ b/applications/test/refPtr/Test-refPtr.C @@ -32,14 +32,22 @@ struct myScalarField : public scalarField template<class T> void printInfo(const refPtr<T>& item, const bool verbose = false) { - Info<< "refPtr valid:" << Switch::name(item.valid()) + Info<< "refPtr good:" << Switch::name(item.good()) << " pointer:" << Switch::name(item.is_pointer()) - << " addr: " << name(item.get()) + << " addr: " << Foam::name(item.get()) << " movable:" << Switch(item.movable()); - Info<< nl; - - if (verbose && item.valid()) + Info<< " move-constructible:" + << std::is_move_constructible<refPtr<T>>::value + << " move-assignable:" + << std::is_move_assignable<refPtr<T>>::value + << " nothrow:" + << std::is_nothrow_move_assignable<refPtr<T>>::value + << " trivially:" + << std::is_trivially_move_assignable<refPtr<T>>::value + << nl; + + if (verbose && item) { Info<< "content: " << item() << nl; } diff --git a/applications/test/tmp/Test-tmp.C b/applications/test/tmp/Test-tmp.C index 366fcb10998..52f1fdac2f1 100644 --- a/applications/test/tmp/Test-tmp.C +++ b/applications/test/tmp/Test-tmp.C @@ -32,18 +32,26 @@ struct myScalarField : public scalarField template<class T> void printInfo(const tmp<T>& item, const bool verbose = false) { - Info<< "tmp valid:" << Switch::name(item.valid()) + Info<< "tmp good:" << Switch::name(item.good()) << " pointer:" << Switch::name(item.is_pointer()) - << " addr: " << name(item.get()) + << " addr: " << Foam::name(item.get()) << " movable:" << Switch(item.movable()); - - if (item.valid()) + if (item) { Info<< " refCount:" << item->count(); } - Info<< nl; - if (verbose && item.valid()) + Info<< " move-constructible:" + << std::is_move_constructible<tmp<T>>::value + << " move-assignable:" + << std::is_move_assignable<tmp<T>>::value + << " nothrow:" + << std::is_nothrow_move_assignable<tmp<T>>::value + << " trivially:" + << std::is_trivially_move_assignable<tmp<T>>::value + << nl; + + if (verbose && item) { Info<< "content: " << item() << nl; } diff --git a/src/OpenFOAM/fields/Fields/Field/PrecisionAdaptor/PrecisionAdaptor.H b/src/OpenFOAM/fields/Fields/Field/PrecisionAdaptor/PrecisionAdaptor.H index 94372dab7ba..e225a30981c 100644 --- a/src/OpenFOAM/fields/Fields/Field/PrecisionAdaptor/PrecisionAdaptor.H +++ b/src/OpenFOAM/fields/Fields/Field/PrecisionAdaptor/PrecisionAdaptor.H @@ -128,7 +128,7 @@ public: bool active() const noexcept { // Same as refPtr::movable() - return (this->is_pointer() && this->valid()); + return (this->is_pointer() && this->good()); } //- Commit adapted content changes (no-op for const adaptor) @@ -253,13 +253,13 @@ public: bool active() const noexcept { // Same as refPtr::movable() - return (this->is_pointer() && this->valid()); + return (this->is_pointer() && this->good()); } //- Commit adapted content changes back to original input (as required) void commit() { - if (this->active() && orig_.valid()) + if (this->active() && orig_.good()) { const auto& stored = this->cref(); auto& input = orig_.ref(); diff --git a/src/OpenFOAM/memory/autoPtr/autoPtr.H b/src/OpenFOAM/memory/autoPtr/autoPtr.H index af002bc84ad..9b78fe9279f 100644 --- a/src/OpenFOAM/memory/autoPtr/autoPtr.H +++ b/src/OpenFOAM/memory/autoPtr/autoPtr.H @@ -143,7 +143,7 @@ public: // Query //- True if the managed pointer is non-null - bool valid() const noexcept { return bool(ptr_); } + bool good() const noexcept { return bool(ptr_); } // Access @@ -165,6 +165,7 @@ public: // Edit //- Release ownership and return the pointer. + // \remark Method naming consistent with std::unique_ptr inline T* release() noexcept; //- Same as \c release(). @@ -175,6 +176,7 @@ public: // \remark Method naming consistent with Foam::tmp void clear() noexcept { reset(nullptr); } + //- Delete managed object and set to new given pointer // \remark Same as move assign, but better for code documentation inline void reset(autoPtr<T>&& other) noexcept; @@ -224,7 +226,7 @@ public: // Casting - //- True if pointer/reference is non-null. Same as valid() + //- True if pointer/reference is non-null. Same as good() explicit operator bool() const noexcept { return bool(ptr_); } //- Cast to pointer type @@ -267,6 +269,9 @@ public: // Housekeeping + //- Identical to good(), or bool operator + bool valid() const noexcept { return bool(ptr_); } + //- Deprecated(2020-07) True if the managed pointer is null // // \deprecated(2020-07) - use bool operator @@ -285,6 +290,8 @@ public: }; +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + // Global Functions //- Specializes the Swap algorithm for autoPtr. diff --git a/src/OpenFOAM/memory/refPtr/refPtr.H b/src/OpenFOAM/memory/refPtr/refPtr.H index b78b5b0d8da..4469d09a875 100644 --- a/src/OpenFOAM/memory/refPtr/refPtr.H +++ b/src/OpenFOAM/memory/refPtr/refPtr.H @@ -151,8 +151,8 @@ public: // Query - //- True for non-null pointer/reference - bool valid() const noexcept { return bool(ptr_); } + //- True if pointer/reference is non-null. + bool good() const noexcept { return bool(ptr_); } //- If the stored/referenced content is const bool is_const() const noexcept { return type_ == CREF; } @@ -187,20 +187,27 @@ public: // Fatal for a null managed pointer. inline T& constCast() const; + //- Return a shallow copy as a wrapped reference, preserving the + //- const/non-const status. + inline refPtr<T> shallowClone() const noexcept; + // Edit //- Release ownership and return the pointer. //- A no-op for reference objects (returns nullptr). + // \remark Method naming consistent with std::unique_ptr inline T* release() noexcept; //- Return managed pointer for reuse, or clone() the object reference. + // \remark Method naming consistent with Foam::tmp inline T* ptr() const; //- If object pointer points to valid object: //- delete object and set pointer to nullptr inline void clear() const noexcept; + //- Clear existing and transfer ownership. inline void reset(refPtr<T>&& other) noexcept; @@ -213,6 +220,10 @@ public: //- Clear existing and transfer ownership from unique_ptr void reset(std::unique_ptr<T>&& other) { reset(other.release()); } + + //- Clear existing and set (const) reference from other + inline void cref(const refPtr<T>& other) noexcept; + //- Clear existing and set (const) reference inline void cref(const T& obj) noexcept; @@ -220,6 +231,7 @@ public: // The pointer can be null, which is handled like a clear(). inline void cref(const T* p) noexcept; + //- Clear existing and set (non-const) reference inline void ref(T& obj) noexcept; @@ -227,6 +239,7 @@ public: // The pointer can be null, which is handled like a clear(). inline void ref(T* p) noexcept; + //- Swaps the managed object with other. inline void swap(refPtr<T>& other) noexcept; @@ -252,11 +265,17 @@ public: //- Return const reference to the object - same as cref() method. const T& operator()() const { return cref(); } + + // Casting + + //- True if pointer/reference is non-null. Same as good() + explicit operator bool() const noexcept { return bool(ptr_); } + //- Cast to underlying data type, using the cref() method. operator const T&() const { return cref(); } - //- True if pointer/reference is non-null. Same as valid() - explicit operator bool() const noexcept { return bool(ptr_); } + + // Assignment //- Transfer ownership of the managed pointer. // Fatal for a null managed pointer or if the object is const. @@ -278,6 +297,9 @@ public: // Housekeeping + //- Identical to good(), or bool operator + bool valid() const noexcept { return bool(ptr_); } + //- Deprecated(2020-07) True if a null managed pointer // // \deprecated(2020-07) - use bool operator @@ -286,6 +308,8 @@ public: }; +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + // Global Functions //- Specialized Swap algorithm for refPtr. diff --git a/src/OpenFOAM/memory/refPtr/refPtrI.H b/src/OpenFOAM/memory/refPtr/refPtrI.H index 0664701b180..ff5ce5ee8f4 100644 --- a/src/OpenFOAM/memory/refPtr/refPtrI.H +++ b/src/OpenFOAM/memory/refPtr/refPtrI.H @@ -167,6 +167,8 @@ inline Foam::refPtr<T>::refPtr(const refPtr<T>& rhs, bool reuse) } +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + template<class T> inline Foam::refPtr<T>::~refPtr() { @@ -200,7 +202,7 @@ inline const T& Foam::refPtr<T>::cref() const template<class T> inline T& Foam::refPtr<T>::ref() const { - if (type_ == CREF) + if (is_const()) { FatalErrorInFunction << "Attempted non-const reference to const object: " @@ -225,6 +227,21 @@ inline T& Foam::refPtr<T>::constCast() const } +template<class T> +inline Foam::refPtr<T> Foam::refPtr<T>::shallowClone() const noexcept +{ + refPtr<T> dup; + + if (ptr_) + { + dup.ptr_ = ptr_; + dup.type_ = (is_const() ? CREF : REF); + } + + return dup; +} + + template<class T> inline T* Foam::refPtr<T>::release() noexcept { @@ -299,6 +316,20 @@ inline void Foam::refPtr<T>::reset(refPtr<T>&& other) noexcept } +template<class T> +inline void Foam::refPtr<T>::cref(const refPtr<T>& other) noexcept +{ + if (&other == this) + { + return; // Self-assignment is a no-op + } + + clear(); + ptr_ = other.ptr_; + type_ = (ptr_ ? CREF : PTR); +} + + template<class T> inline void Foam::refPtr<T>::cref(const T& obj) noexcept { @@ -368,7 +399,7 @@ inline const T& Foam::refPtr<T>::operator*() const template<class T> inline T& Foam::refPtr<T>::operator*() { - if (type_ == CREF) + if (is_const()) { FatalErrorInFunction << "Attempt to cast const object to non-const: " @@ -403,7 +434,7 @@ inline const T* Foam::refPtr<T>::operator->() const template<class T> inline T* Foam::refPtr<T>::operator->() { - if (type_ == CREF) + if (is_const()) { FatalErrorInFunction << "Attempt to cast const object to non-const: " diff --git a/src/OpenFOAM/memory/tmp/tmp.H b/src/OpenFOAM/memory/tmp/tmp.H index ccd2efc6242..c24f5260fbb 100644 --- a/src/OpenFOAM/memory/tmp/tmp.H +++ b/src/OpenFOAM/memory/tmp/tmp.H @@ -166,8 +166,8 @@ public: // Query - //- True if pointer/reference is non-null - bool valid() const noexcept { return bool(ptr_); } + //- True if pointer/reference is non-null. + bool good() const noexcept { return bool(ptr_); } //- If the stored/referenced content is const bool is_const() const noexcept { return type_ == CREF; } @@ -175,9 +175,6 @@ public: //- True if this is a managed pointer (not a reference) bool is_pointer() const noexcept { return type_ == PTR; } - //- Identical to is_pointer() - bool isTmp() const noexcept { return type_ == PTR; } - //- True if this is a non-null managed pointer with a unique ref-count inline bool movable() const noexcept; @@ -215,12 +212,17 @@ public: //- delete object and set pointer to nullptr inline void clear() const noexcept; + //- Clear existing and transfer ownership. inline void reset(tmp<T>&& other) noexcept; //- Delete managed temporary object and set to new given pointer inline void reset(T* p = nullptr) noexcept; + + //- Clear existing and set (const) reference from other + inline void cref(const tmp<T>& other) noexcept; + //- Clear existing and set (const) reference inline void cref(const T& obj) noexcept; @@ -228,6 +230,7 @@ public: // The pointer can be null, which is handled like a clear(). inline void cref(const T* p) noexcept; + //- Clear existing and set to (non-const) reference inline void ref(T& obj) noexcept; @@ -235,12 +238,17 @@ public: // The pointer can be null, which is handled like a clear(). inline void ref(T* p) noexcept; + //- Swaps the managed object with other. inline void swap(tmp<T>& other) noexcept; // Member Operators + // Note: no 'operator*()' types since there are large chunks + // of code that use tmp\<Field\> and Field interchangeable + // Eg, \code (a * b) - and the '*' would be misinterpreted + //- Dereferences (const) pointer to the managed object. // Fatal for a null managed pointer. inline const T* operator->() const; @@ -252,11 +260,17 @@ public: //- Return const reference to the object - same as cref() method. const T& operator()() const { return cref(); } + + // Casting + + //- True if pointer/reference is non-null. Same as good() + explicit operator bool() const noexcept { return bool(ptr_); } + //- Cast to underlying data type, using the cref() method. operator const T&() const { return cref(); } - //- True if pointer/reference is non-null. Same as valid() - explicit operator bool() const noexcept { return bool(ptr_); } + + // Assignment //- Transfer ownership of the managed pointer. // Fatal for a null managed pointer or if the object is const. @@ -275,6 +289,12 @@ public: // Housekeeping + //- Identical to good(), or bool operator + bool valid() const noexcept { return bool(ptr_); } + + //- Identical to is_pointer() + bool isTmp() const noexcept { return type_ == PTR; } + //- Deprecated(2020-07) True if a null managed pointer // // \deprecated(2020-07) - use bool operator @@ -283,6 +303,8 @@ public: }; +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + // Global Functions //- Specialized Swap algorithm for tmp. diff --git a/src/OpenFOAM/memory/tmp/tmpI.H b/src/OpenFOAM/memory/tmp/tmpI.H index b58eb7df37e..d378e2a612f 100644 --- a/src/OpenFOAM/memory/tmp/tmpI.H +++ b/src/OpenFOAM/memory/tmp/tmpI.H @@ -191,6 +191,8 @@ inline Foam::tmp<T>::tmp(const tmp<T>& rhs, bool reuse) } +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + template<class T> inline Foam::tmp<T>::~tmp() { @@ -224,7 +226,7 @@ inline const T& Foam::tmp<T>::cref() const template<class T> inline T& Foam::tmp<T>::ref() const { - if (type_ == CREF) + if (is_const()) { FatalErrorInFunction << "Attempted non-const reference to const object: " @@ -325,6 +327,20 @@ inline void Foam::tmp<T>::reset(tmp<T>&& other) noexcept } +template<class T> +inline void Foam::tmp<T>::cref(const tmp<T>& other) noexcept +{ + if (&other == this) + { + return; // Self-assignment is a no-op + } + + clear(); + ptr_ = other.ptr_; + type_ = (ptr_ ? CREF : PTR); +} + + template<class T> inline void Foam::tmp<T>::cref(const T& obj) noexcept { @@ -395,7 +411,7 @@ inline const T* Foam::tmp<T>::operator->() const template<class T> inline T* Foam::tmp<T>::operator->() { - if (type_ == CREF) + if (is_const()) { FatalErrorInFunction << "Attempt to cast const object to non-const: " -- GitLab