ENH: improve autoPtr/refPtr/tmp consistency (#2571)

- disallow inadvertant casting and hidden copy constructions etc
This commit is contained in:
Mark Olesen 2022-09-05 13:39:01 +02:00
parent 052d8b13e3
commit c031f7d00a
11 changed files with 541 additions and 389 deletions

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018-2020 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,7 +27,6 @@ License
// #define Foam_autoPtr_deprecate_setMethod
#include <memory>
#include "autoPtr.H"
#include "labelList.H"
#include "ListOps.H"
@ -77,6 +76,14 @@ autoPtr<T> testNullReturn2()
}
template<class T>
struct DerivedList : public List<T>
{
// Inherit constructors
using List<T>::List;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
@ -254,6 +261,16 @@ int main(int argc, char *argv[])
// autoPtr<labelList> ptr2 = testNullReturn2<labelList>();
}
{
auto input1 = autoPtr<DerivedList<label>>::New(label(10), 1);
auto input2 = autoPtr<DerivedList<scalar>>::New(label(10), 1.0);
autoPtr<labelList> ptr1(std::move(input1));
// Does not compile: ptr1 = std::move(input2);
// Does not compile: ptr1 = autoPtr<List<scalar>>::New(label(10), 2);
}
return 0;
}

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020-2021 OpenCFD Ltd.
Copyright (C) 2020-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
@ -19,6 +19,9 @@ Description
\*---------------------------------------------------------------------------*/
#include "primitiveFields.H"
#include "autoPtr.H"
#include "refPtr.H"
#include "tmp.H"
#include "Switch.H"
using namespace Foam;
@ -29,6 +32,36 @@ struct myScalarField : public scalarField
};
template<class T>
void constructInfo()
{
Info<< " move-constructible:"
<< std::is_move_constructible<T>::value
<< " move-assignable:"
<< std::is_move_assignable<T>::value
<< " nothrow:"
<< std::is_nothrow_move_assignable<T>::value
<< " trivially:"
<< std::is_trivially_move_assignable<T>::value
<< nl;
}
template<class T>
void printInfo(const autoPtr<T>& item, const bool verbose = false)
{
Info<< "autoPtr good:" << Switch::name(item.good())
<< " addr: " << Foam::name(item.get());
constructInfo<autoPtr<T>>();
if (verbose && item)
{
Info<< "content: " << item() << nl;
}
}
template<class T>
void printInfo(const refPtr<T>& item, const bool verbose = false)
{
@ -37,15 +70,24 @@ void printInfo(const refPtr<T>& item, const bool verbose = false)
<< " addr: " << Foam::name(item.get())
<< " movable:" << Switch(item.movable());
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;
constructInfo<refPtr<T>>();
if (verbose && item)
{
Info<< "content: " << item() << nl;
}
}
template<class T>
void printInfo(const tmp<T>& item, const bool verbose = false)
{
Info<< "tmp good:" << Switch::name(item.good())
<< " pointer:" << Switch::name(item.is_pointer())
<< " addr: " << Foam::name(item.get())
<< " movable:" << Switch(item.movable());
constructInfo<tmp<T>>();
if (verbose && item)
{
@ -101,6 +143,62 @@ int main()
printInfo(tfld3, true);
}
{
refPtr<scalarField> tfld1;
auto aptr = autoPtr<scalarField>::New(2, scalar(2));
tmp<scalarField> tfld2;
printInfo(tfld2, true);
tfld2 = new scalarField(10, Zero);
/*
tfld2 = aptr.get();
// tfld1.reset(aptr);
// tfld1 = std::move(aptr);
// tfld1 = aptr;
Info<< nl << "From autoPtr" << nl;
printInfo(aptr, true);
//& Info<< nl << "Construct from autoPtr" << nl;
//& // refPtr<scalarField> tfld2(autoPtr<scalarField>::New(10, scalar(2)));
//& printInfo(tfld2, true);
*/
}
{
auto aptr1 = autoPtr<labelField>::New(2, Zero);
//auto aptr1 = autoPtr<scalarField>::New(2, scalar(2));
auto aptr2 = autoPtr<scalarField>::New(2, scalar(2));
refPtr<scalarField> tfld2(std::move(aptr2));
// aptr2 = std::move(aptr1);
}
{
auto tptr1 = tmp<labelField>::New(2, Zero);
auto aptr1 = autoPtr<labelField>::New(2, Zero);
auto tfld2 = refPtr<labelField>::New(2, Zero);
// Deleted: refPtr<labelField> tfld1(aptr1);
refPtr<labelField> tfld1;
// refPtr<labelField> tfld1(std::move(tptr1));
// refPtr<labelField> tfld1(tptr1);
tfld1 = std::move(aptr1);
// tfld1.reset(aptr1);
// tfld1.reset(tfld2);
// tfld1 = std::move(tptr1);
// Does not compile: tfld1.ref(tptr1);
// Deleted: tfld1.cref(tptr1);
// Deleted: tfld1.ref(aptr1);
}
Info<< "\nEnd" << endl;
return 0;

View File

@ -19,6 +19,9 @@ Description
\*---------------------------------------------------------------------------*/
#include "primitiveFields.H"
#include "autoPtr.H"
#include "refPtr.H"
#include "tmp.H"
#include "Switch.H"
using namespace Foam;
@ -126,6 +129,28 @@ int main()
printInfo(tfld2);
}
{
auto tptr1 = refPtr<labelField>::New(2, Zero);
auto aptr1 = autoPtr<labelField>::New(2, Zero);
// Deleted: tmp<labelField> tfld1(aptr1);
// tmp<labelField> tfld1(std::move(aptr1));
// tmp<labelField> tfld1(std::move(tptr1));
tmp<labelField> tfld1;
//tfld1.cref(tptr1);
//tfld1.cref(aptr1);
// refPtr<labelField> tfld1(std::move(tptr1));
// refPtr<labelField> tfld1(tptr1);
// tfld1 = std::move(aptr1);
// tfld1 = std::move(tptr1);
// Does not compile: tfld1.ref(tptr1);
// Deleted: tfld1.cref(tptr1);
// Deleted: tfld1.ref(aptr1);
}
Info<< "\nEnd" << endl;
return 0;

View File

@ -1184,7 +1184,7 @@ int main(int argc, char *argv[])
false
);
masterMeshPtr = fvMeshes[0];
masterMeshPtr.cref(fvMeshes[0]);
}

View File

@ -41,6 +41,9 @@ Note
SourceFiles
autoPtrI.H
See also
Foam::refPtr
\*---------------------------------------------------------------------------*/
#ifndef Foam_autoPtr_H
@ -80,62 +83,92 @@ public:
typedef T* pointer;
// Constructors
//- Construct with no managed pointer.
constexpr autoPtr() noexcept
:
ptr_(nullptr)
{}
//- Implicit construct from literal nullptr: no managed pointer
constexpr autoPtr(std::nullptr_t) noexcept
:
ptr_(nullptr)
{}
//- Construct, taking ownership of the pointer.
explicit autoPtr(T* p) noexcept
:
ptr_(p)
{}
//- Move construct, transferring ownership.
autoPtr(autoPtr<T>&& rhs) noexcept
:
ptr_(rhs.release())
{}
//- Move construct, transferring ownership from derived type.
// U must be derivable from T
// \note Future check std::enable_if + std::is_convertible ?
template<class U>
explicit autoPtr(autoPtr<U>&& rhs)
:
ptr_(rhs.release())
{}
//- Move construct from unique_ptr, transferring ownership.
explicit autoPtr(std::unique_ptr<T>&& rhs) noexcept
:
ptr_(rhs.release())
{}
//- A move construct disguised as a copy construct (transfers ownership)
// \remark This should ideally be deleted - pending cleanup of code
// currently relying on this behaviour.
#ifdef Foam_autoPtr_copyConstruct
autoPtr(const autoPtr<T>& rhs) noexcept
:
ptr_(const_cast<autoPtr<T>&>(rhs).release())
{}
#else
autoPtr(const autoPtr<T>&) = delete;
#endif
//- Destructor: deletes managed pointer
~autoPtr() noexcept
{
delete ptr_;
}
// Factory Methods
//- Construct autoPtr of T with forwarding arguments
//- Construct autoPtr with forwarding arguments
// \param args list of arguments with which an instance of T
// will be constructed.
//
// \note Similar to std::make_unique, but the overload for
// array types is not disabled.
template<class... Args>
inline static autoPtr<T> New(Args&&... args);
static autoPtr<T> New(Args&&... args)
{
return autoPtr<T>(new T(std::forward<Args>(args)...));
}
//- Construct autoPtr from derived type with forwarding arguments
// \param args list of arguments with which an instance of U
// will be constructed.
//
// \note Similar to New but for derived types.
// Future check for std::is_base_of ?
// Future check std::enable_if + std::is_convertible ?
template<class U, class... Args>
inline static autoPtr<T> NewFrom(Args&&... args);
// Constructors
//- Construct with no managed pointer.
inline constexpr autoPtr() noexcept;
//- Construct with no managed pointer (literal nullptr).
inline constexpr autoPtr(std::nullptr_t) noexcept;
//- Construct, taking ownership of the pointer.
inline explicit autoPtr(T* p) noexcept;
//- Move construct, transferring ownership.
inline autoPtr(autoPtr<T>&& ap) noexcept;
//- Move construct, transferring ownership from derived type.
// U must be derivable from T
// \note Future check for std::is_base_of ?
template<class U>
inline explicit autoPtr(autoPtr<U>&& ap);
//- A move construct disguised as a copy construct (transfers ownership)
// \remark This should ideally be deleted - pending cleanup of code
// currently relying on this behaviour.
#ifdef Foam_autoPtr_copyConstruct
autoPtr(const autoPtr<T>& ap) noexcept
:
ptr_(const_cast<autoPtr<T>&>(ap).release())
{}
#else
autoPtr(const autoPtr<T>& ap) = delete;
#endif
//- Deletes the managed pointer
inline ~autoPtr() noexcept;
static autoPtr<T> NewFrom(Args&&... args)
{
return autoPtr<T>(new U(std::forward<Args>(args)...));
}
// Member Functions
@ -176,14 +209,13 @@ public:
// \remark Method naming consistent with Foam::tmp
void clear() noexcept { reset(nullptr); }
//- Delete managed object and set to new given pointer
inline void reset(T* p = nullptr) noexcept;
//- 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;
//- Delete managed object and set to new given pointer
inline void reset(T* p = nullptr) noexcept;
//- Swaps the managed object with other autoPtr.
inline void swap(autoPtr<T>& other) noexcept;
@ -252,19 +284,26 @@ public:
//- No copy assignment from plain pointer (uncontrolled access)
void operator=(T* p) = delete;
//- Transfer object ownership from parameter
inline void operator=(autoPtr<T>&& ap) noexcept;
//- Transfer object ownership from parameter
template<class U>
inline void operator=(autoPtr<U>&& ap) noexcept;
//- No move assignment disguised as a copy assignment
// \deprecated(2018-02) can have unintended behaviour
void operator=(const autoPtr<T>& ap) = delete;
void operator=(const autoPtr<T>&) = delete;
//- Transfer object ownership from parameter
void operator=(autoPtr<T>&& other) noexcept { reset(std::move(other)); }
//- Transfer object ownership from parameter
// \note Future check std::enable_if + std::is_convertible ?
template<class U>
void operator=(autoPtr<U>&& other) noexcept
{
reset(other.release());
}
//- Transfer ownership by move assignment from unique_ptr
void operator=(std::unique_ptr<T>&& other) { reset(other.release()); }
//- Reset via assignment from literal nullptr
inline void operator=(std::nullptr_t) noexcept;
void operator=(std::nullptr_t) noexcept { reset(nullptr); }
// Housekeeping
@ -294,8 +333,7 @@ public:
// Global Functions
//- Specializes the Swap algorithm for autoPtr.
// Swaps the pointers of lhs and rhs. Calls \c lhs.swap(rhs)
//- Specializes the Swap algorithm for autoPtr (swaps pointers).
template<class T>
void Swap(autoPtr<T>& lhs, autoPtr<T>& rhs)
{

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2016-2020 OpenCFD Ltd.
Copyright (C) 2016-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -29,71 +29,6 @@ License
#include "error.H"
#include <typeinfo>
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<class T>
template<class... Args>
inline Foam::autoPtr<T> Foam::autoPtr<T>::New(Args&&... args)
{
return autoPtr<T>(new T(std::forward<Args>(args)...));
}
template<class T>
template<class U, class... Args>
inline Foam::autoPtr<T> Foam::autoPtr<T>::NewFrom(Args&&... args)
{
return autoPtr<T>(new U(std::forward<Args>(args)...));
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class T>
inline constexpr Foam::autoPtr<T>::autoPtr() noexcept
:
ptr_(nullptr)
{}
template<class T>
inline constexpr Foam::autoPtr<T>::autoPtr(std::nullptr_t) noexcept
:
ptr_(nullptr)
{}
template<class T>
inline Foam::autoPtr<T>::autoPtr(T* p) noexcept
:
ptr_(p)
{}
template<class T>
inline Foam::autoPtr<T>::autoPtr(autoPtr<T>&& ap) noexcept
:
ptr_(ap.release())
{}
template<class T>
template<class U>
inline Foam::autoPtr<T>::autoPtr(autoPtr<U>&& ap)
:
ptr_(ap.release())
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
template<class T>
inline Foam::autoPtr<T>::~autoPtr() noexcept
{
reset(nullptr);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T>
@ -108,7 +43,7 @@ inline T* Foam::autoPtr<T>::release() noexcept
template<class T>
inline void Foam::autoPtr<T>::reset(T* p) noexcept
{
if (ptr_) delete ptr_;
delete ptr_;
ptr_ = p;
}
@ -116,11 +51,13 @@ inline void Foam::autoPtr<T>::reset(T* p) noexcept
template<class T>
inline void Foam::autoPtr<T>::reset(autoPtr<T>&& other) noexcept
{
if (&other != this)
// Could also make Fatal with FULLDEBUG
if (&other == this)
{
// Ignore self-assignment
reset(other.release());
return; // No self-assignment
}
reset(other.release());
}
@ -204,34 +141,4 @@ inline const T& Foam::autoPtr<T>::operator()() const
}
template<class T>
inline void Foam::autoPtr<T>::operator=(autoPtr<T>&& ap) noexcept
{
if (this != &ap)
{
// Ignore self-assignment
reset(ap.release());
}
}
template<class T>
template<class U>
inline void Foam::autoPtr<T>::operator=(autoPtr<U>&& ap) noexcept
{
if (this != &ap)
{
// Ignore self-assignment
reset(ap.release());
}
}
template<class T>
inline void Foam::autoPtr<T>::operator=(std::nullptr_t) noexcept
{
reset(nullptr);
}
// ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016 OpenFOAM Foundation
Copyright (C) 2018-2021 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -89,44 +89,18 @@ public:
typedef Foam::refCount::zero refCount;
// Factory Methods
//- Construct refPtr of T with forwarding arguments
// \param args list of arguments with which an instance of T
// will be constructed.
//
// \note Similar to std::make_shared, but the overload for
// array types is not disabled.
template<class... Args>
inline static refPtr<T> New(Args&&... args);
//- Construct refPtr from derived type with forwarding arguments
// \param args list of arguments with which an instance of U
// will be constructed.
//
// \note Similar to New but for derived types
template<class U, class... Args>
inline static refPtr<T> NewFrom(Args&&... args);
// Constructors
//- Construct with no managed pointer.
inline constexpr refPtr() noexcept;
//- Construct with no managed pointer (literal nullptr).
//- Implicit construct from literal nullptr: no managed pointer
inline constexpr refPtr(std::nullptr_t) noexcept;
//- Construct, taking ownership of the pointer.
inline explicit constexpr refPtr(T* p) noexcept;
//- Move construct from autoPtr, transferring ownership.
inline explicit refPtr(autoPtr<T>&& ptr) noexcept;
//- Move construct from unique_ptr, transferring ownership.
inline explicit refPtr(std::unique_ptr<T>&& ptr) noexcept;
//- Construct for a const reference to an object.
//- Implicit construct for a const reference to an object.
inline constexpr refPtr(const T& obj) noexcept;
//- Move construct, transferring ownership.
@ -138,12 +112,58 @@ public:
//- Copy/move construct. Optionally reusing pointer.
inline refPtr(const refPtr<T>& rhs, bool reuse);
//- Move construct from unique_ptr, transferring ownership.
inline explicit refPtr(std::unique_ptr<T>&& rhs) noexcept;
//- No copy construct from autoPtr,
//- also avoids implicit cast to object or pointer
refPtr(const autoPtr<T>&) = delete;
//- Move construct from autoPtr, transferring ownership.
inline explicit refPtr(autoPtr<T>&& rhs) noexcept;
//- Reference tmp contents or transfer ownership if requested/possible
inline refPtr(const tmp<T>& rhs, bool reuse);
//- Reference the tmp contents
inline explicit refPtr(const tmp<T>& rhs);
//- Move construct from tmp, transfer ownership if possible.
inline explicit refPtr(tmp<T>&& rhs);
//- Destructor: deletes managed pointer
inline ~refPtr();
inline ~refPtr() noexcept;
// Member Functions
// Factory Methods
//- Construct refPtr with forwarding arguments
// \param args list of arguments with which an instance of T
// will be constructed.
//
// \note Similar to std::make_shared, but the overload for
// array types is not disabled.
template<class... Args>
static refPtr<T> New(Args&&... args)
{
return refPtr<T>(new T(std::forward<Args>(args)...));
}
//- Construct refPtr from derived type with forwarding arguments
// \param args list of arguments with which an instance of U
// will be constructed.
//
// \note Similar to New but for derived types.
// Future check std::enable_if + std::is_convertible ?
template<class U, class... Args>
static refPtr<T> NewFrom(Args&&... args)
{
return refPtr<T>(new U(std::forward<Args>(args)...));
}
// Static Member Functions
//- The type-name, constructed from type-name of T
inline static word typeName();
@ -207,12 +227,14 @@ public:
//- delete object and set pointer to nullptr
inline void clear() const noexcept;
//- Delete managed pointer and set to new given pointer
inline void reset(T* p = nullptr) noexcept;
//- Clear existing and transfer ownership.
inline void reset(refPtr<T>&& other) noexcept;
//- Delete managed pointer and set to new given pointer
inline void reset(T* p = nullptr) noexcept;
//- No reset from autoPtr reference (potentially confusing)
void reset(const autoPtr<T>&) = delete;
//- Clear existing and transfer ownership from autoPtr.
void reset(autoPtr<T>&& other) noexcept { reset(other.release()); }
@ -220,6 +242,8 @@ public:
//- Clear existing and transfer ownership from unique_ptr
void reset(std::unique_ptr<T>&& other) { reset(other.release()); }
//- Reference tmp contents or transfer pointer ownership if possible
inline void reset(tmp<T>& rhs, bool reuse);
//- Clear existing and set (const) reference from other
inline void cref(const refPtr<T>& other) noexcept;
@ -231,6 +255,11 @@ public:
// The pointer can be null, which is handled like a clear().
inline void cref(const T* p) noexcept;
//- Avoid inadvertent casting (to object or pointer)
void cref(const autoPtr<T>&) = delete;
//- Avoid inadvertent casting (to object)
void cref(const tmp<T>&) = delete;
//- Clear existing and set (non-const) reference
inline void ref(T& obj) noexcept;
@ -239,6 +268,11 @@ public:
// The pointer can be null, which is handled like a clear().
inline void ref(T* p) noexcept;
//- Avoid inadvertent casting (to object or pointer)
void ref(const autoPtr<T>&) = delete;
//- Avoid inadvertent casting (object)
void ref(const tmp<T>&) = delete;
//- Swaps the managed object with other.
inline void swap(refPtr<T>& other) noexcept;
@ -277,19 +311,34 @@ public:
// Assignment
//- Transfer ownership of the managed pointer.
//- Transfer ownership of managed pointer.
// Fatal for a null managed pointer or if the object is const.
inline void operator=(const refPtr<T>& other);
//- Clear existing and transfer ownership.
inline void operator=(refPtr<T>&& other) noexcept;
void operator=(refPtr<T>&& other) noexcept { reset(std::move(other)); }
//- Take ownership of the pointer.
// Fatal for a null pointer
inline void operator=(T* p);
//- No copy assignment from plain pointer (uncontrolled access)
void operator=(T* p) = delete;
//- Reset via assignment from literal nullptr
inline void operator=(std::nullptr_t) noexcept;
void operator=(std::nullptr_t) noexcept { reset(nullptr); }
//- No copy assignment from autoPtr (can have unintended behaviour)
void operator=(const autoPtr<T>&) = delete;
//- Transfer ownership by move assignment from autoPtr.
void operator=(autoPtr<T>&& other) noexcept { reset(other.release()); }
//- Transfer ownership by move assignment from unique_ptr
void operator=(std::unique_ptr<T>&& other) { reset(other.release()); }
//- No copy assignment from tmp
void operator=(const tmp<T>&) = delete;
//- Move construct, transferring pointer ownership if possible.
inline void operator=(tmp<T>&& other);
//- Conversion to tmp, releases pointer or shallow-copies reference
inline operator tmp<T>();
@ -312,8 +361,7 @@ public:
// Global Functions
//- Specialized Swap algorithm for refPtr.
// Swaps the pointers and types of lhs and rhs. Calls \c lhs.swap(rhs)
//- Specializes the Swap algorithm for refPtr (swaps pointers and types).
template<class T>
void Swap(refPtr<T>& lhs, refPtr<T>& rhs)
{

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2017 OpenFOAM Foundation
Copyright (C) 2018-2021 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -34,23 +34,7 @@ License
template<class T>
inline Foam::word Foam::refPtr<T>::typeName()
{
return "refPtr<" + word(typeid(T).name()) + '>';
}
template<class T>
template<class... Args>
inline Foam::refPtr<T> Foam::refPtr<T>::New(Args&&... args)
{
return refPtr<T>(new T(std::forward<Args>(args)...));
}
template<class T>
template<class U, class... Args>
inline Foam::refPtr<T> Foam::refPtr<T>::NewFrom(Args&&... args)
{
return refPtr<T>(new U(std::forward<Args>(args)...));
return Foam::word("refPtr<" + std::string(typeid(T).name()) + '>', false);
}
@ -80,19 +64,6 @@ inline constexpr Foam::refPtr<T>::refPtr(T* p) noexcept
{}
template<class T>
inline Foam::refPtr<T>::refPtr(autoPtr<T>&& rhs) noexcept
:
refPtr<T>(rhs.release())
{}
template<class T>
inline Foam::refPtr<T>::refPtr(std::unique_ptr<T>&& rhs) noexcept
:
refPtr<T>(rhs.release())
{}
template<class T>
inline constexpr Foam::refPtr<T>::refPtr(const T& obj) noexcept
@ -119,7 +90,7 @@ inline Foam::refPtr<T>::refPtr(const refPtr<T>& rhs)
ptr_(rhs.ptr_),
type_(rhs.type_)
{
if (type_ == PTR)
if (is_pointer())
{
if (ptr_)
{
@ -128,7 +99,7 @@ inline Foam::refPtr<T>::refPtr(const refPtr<T>& rhs)
else
{
FatalErrorInFunction
<< "Attempted copy of a deallocated "
<< "Attempted copy/move of a deallocated "
<< this->typeName()
<< abort(FatalError);
}
@ -142,14 +113,14 @@ inline Foam::refPtr<T>::refPtr(const refPtr<T>& rhs, bool reuse)
ptr_(rhs.ptr_),
type_(rhs.type_)
{
if (type_ == PTR)
if (is_pointer())
{
if (ptr_)
{
if (reuse)
{
rhs.ptr_ = nullptr;
// Note: rhs.type_ already set as PTR
rhs.type_ = PTR;
}
else
{
@ -159,7 +130,7 @@ inline Foam::refPtr<T>::refPtr(const refPtr<T>& rhs, bool reuse)
else
{
FatalErrorInFunction
<< "Attempted copy of a deallocated "
<< "Attempted copy/move of a deallocated "
<< this->typeName()
<< abort(FatalError);
}
@ -167,10 +138,51 @@ inline Foam::refPtr<T>::refPtr(const refPtr<T>& rhs, bool reuse)
}
template<class T>
inline Foam::refPtr<T>::refPtr(std::unique_ptr<T>&& rhs) noexcept
:
refPtr<T>(rhs.release())
{}
template<class T>
inline Foam::refPtr<T>::refPtr(autoPtr<T>&& rhs) noexcept
:
refPtr<T>(rhs.release())
{}
template<class T>
inline Foam::refPtr<T>::refPtr(const tmp<T>& rhs, bool reuse)
:
refPtr<T>()
{
reset(const_cast<tmp<T>&>(rhs), reuse);
}
template<class T>
inline Foam::refPtr<T>::refPtr(const tmp<T>& rhs)
:
refPtr<T>()
{
reset(const_cast<tmp<T>&>(rhs), false);
}
template<class T>
inline Foam::refPtr<T>::refPtr(tmp<T>&& rhs)
:
refPtr<T>()
{
reset(const_cast<tmp<T>&>(rhs), true);
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
template<class T>
inline Foam::refPtr<T>::~refPtr()
inline Foam::refPtr<T>::~refPtr() noexcept
{
clear();
}
@ -181,14 +193,14 @@ inline Foam::refPtr<T>::~refPtr()
template<class T>
inline bool Foam::refPtr<T>::movable() const noexcept
{
return (type_ == PTR && ptr_);
return (is_pointer() && ptr_);
}
template<class T>
inline const T& Foam::refPtr<T>::cref() const
{
if (type_ == PTR && !ptr_)
if (is_pointer() && !ptr_)
{
FatalErrorInFunction
<< this->typeName() << " deallocated"
@ -209,7 +221,7 @@ inline T& Foam::refPtr<T>::ref() const
<< this->typeName()
<< abort(FatalError);
}
else if (type_ == PTR && !ptr_)
else if (is_pointer() && !ptr_)
{
FatalErrorInFunction
<< this->typeName() << " deallocated"
@ -245,7 +257,7 @@ inline Foam::refPtr<T> Foam::refPtr<T>::shallowClone() const noexcept
template<class T>
inline T* Foam::refPtr<T>::release() noexcept
{
if (type_ == PTR)
if (is_pointer())
{
T* p = ptr_;
ptr_ = nullptr;
@ -266,7 +278,7 @@ inline T* Foam::refPtr<T>::ptr() const
<< abort(FatalError);
}
if (type_ == PTR)
if (is_pointer())
{
// Release pointer
T* p = ptr_;
@ -282,7 +294,7 @@ inline T* Foam::refPtr<T>::ptr() const
template<class T>
inline void Foam::refPtr<T>::clear() const noexcept
{
if (type_ == PTR && ptr_)
if (is_pointer())
{
delete ptr_;
ptr_ = nullptr;
@ -302,9 +314,10 @@ inline void Foam::refPtr<T>::reset(T* p) noexcept
template<class T>
inline void Foam::refPtr<T>::reset(refPtr<T>&& other) noexcept
{
// Could also make Fatal with FULLDEBUG
if (&other == this)
{
return; // Self-assignment is a no-op
return; // No self-assignment
}
clear();
@ -316,12 +329,40 @@ inline void Foam::refPtr<T>::reset(refPtr<T>&& other) noexcept
}
template<class T>
inline void Foam::refPtr<T>::reset(tmp<T>& other, bool reuse)
{
if (other.get())
{
if (reuse && other.is_pointer())
{
// Acquire pointer.
// Fatal if pointer is not unique (avoids potential leaks)
reset(other.ptr());
}
else if (other.is_const())
{
cref(other.get());
}
else
{
ref(other.get());
}
}
else
{
clear();
}
}
template<class T>
inline void Foam::refPtr<T>::cref(const refPtr<T>& other) noexcept
{
// Could also make Fatal with FULLDEBUG
if (&other == this)
{
return; // Self-assignment is a no-op
return; // No self-assignment
}
clear();
@ -455,18 +496,21 @@ inline T* Foam::refPtr<T>::operator->()
template<class T>
inline void Foam::refPtr<T>::operator=(const refPtr<T>& other)
{
// Could also make Fatal with FULLDEBUG
if (&other == this)
{
return; // Self-assignment is a no-op
return; // No self-assignment
}
clear();
if (other.type_ == PTR)
if (other.is_pointer())
{
ptr_ = other.ptr_;
type_ = PTR;
other.ptr_ = nullptr;
other.type_ = PTR;
if (!ptr_)
{
@ -487,48 +531,16 @@ inline void Foam::refPtr<T>::operator=(const refPtr<T>& other)
template<class T>
inline void Foam::refPtr<T>::operator=(refPtr<T>&& other) noexcept
inline void Foam::refPtr<T>::operator=(tmp<T>&& other)
{
if (&other == this)
{
return; // Self-assignment is a no-op
}
clear();
ptr_ = other.ptr_;
type_ = other.type_;
other.ptr_ = nullptr;
other.type_ = PTR;
}
template<class T>
inline void Foam::refPtr<T>::operator=(T* p)
{
if (!p)
{
FatalErrorInFunction
<< "Attempted copy of a deallocated "
<< this->typeName()
<< abort(FatalError);
}
reset(p);
}
template<class T>
inline void Foam::refPtr<T>::operator=(std::nullptr_t) noexcept
{
reset(nullptr);
reset(other, true); // reuse
}
template<class T>
inline Foam::refPtr<T>::operator tmp<T>()
{
if (type_ == PTR)
if (is_pointer())
{
return tmp<T>(ptr());
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2021 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -48,15 +48,18 @@ See also
#ifndef Foam_tmp_H
#define Foam_tmp_H
#include "autoPtr.H"
#include "refCount.H"
#include "word.H"
#include "stdFoam.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward Declarations
template<class T> class refPtr;
/*---------------------------------------------------------------------------*\
Class tmp Declaration
\*---------------------------------------------------------------------------*/
@ -103,38 +106,18 @@ public:
typedef Foam::refCount refCount;
// Factory Methods
//- Construct tmp of T with forwarding arguments
// \param args list of arguments with which an instance of T
// will be constructed.
//
// \note Similar to std::make_shared, but the overload for
// array types is not disabled.
template<class... Args>
inline static tmp<T> New(Args&&... args);
//- Construct tmp from derived type with forwarding arguments
// \param args list of arguments with which an instance of U
// will be constructed.
//
// \note Similar to New but for derived types
template<class U, class... Args>
inline static tmp<T> NewFrom(Args&&... args);
// Constructors
//- Construct with no managed pointer.
inline constexpr tmp() noexcept;
//- Construct with no managed pointer (literal nullptr).
//- Implicit construct from literal nullptr: no managed pointer
inline constexpr tmp(std::nullptr_t) noexcept;
//- Construct, taking ownership of the pointer.
inline explicit tmp(T* p);
//- Construct for a const reference to an object.
//- Implicit construct for a const reference to an object.
inline constexpr tmp(const T& obj) noexcept;
//- Move construct, transferring ownership.
@ -153,12 +136,50 @@ public:
//- Copy/move construct. Optionally reusing ref-counted pointer.
inline tmp(const tmp<T>& rhs, bool reuse);
//- No copy construct from autoPtr,
//- also avoids implicit cast to object or pointer
tmp(const autoPtr<T>&) = delete;
//- No copy construct from refPtr,
//- also avoids implicit cast to object
tmp(const refPtr<T>&) = delete;
//- Move construct from autoPtr, transferring ownership.
inline explicit tmp(autoPtr<T>&& rhs) noexcept;
//- Destructor: deletes managed pointer when the ref-count is 0
inline ~tmp();
inline ~tmp() noexcept;
// Member Functions
// Factory Methods
//- Construct tmp with forwarding arguments
// \param args list of arguments with which an instance of T
// will be constructed.
//
// \note Similar to std::make_shared, but the overload for
// array types is not disabled.
template<class... Args>
static tmp<T> New(Args&&... args)
{
return tmp<T>(new T(std::forward<Args>(args)...));
}
//- Construct tmp from derived type with forwarding arguments
// \param args list of arguments with which an instance of U
// will be constructed.
//
// \note Similar to New but for derived types.
// Future check std::enable_if + std::is_convertible ?
template<class U, class... Args>
static tmp<T> NewFrom(Args&&... args)
{
return tmp<T>(new U(std::forward<Args>(args)...));
}
// Static Member Functions
//- The type-name, constructed from type-name of T
inline static word typeName();
@ -212,13 +233,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;
//- Avoid inadvertent casting (to object or pointer)
void reset(const autoPtr<T>&) = delete;
//- Avoid inadvertent casting (to object)
void reset(const refPtr<T>&) = delete;
//- Clear existing and set (const) reference from other
inline void cref(const tmp<T>& other) noexcept;
@ -230,6 +255,11 @@ public:
// The pointer can be null, which is handled like a clear().
inline void cref(const T* p) noexcept;
//- Avoid inadvertent casting (to object or pointer)
void cref(const autoPtr<T>&) = delete;
//- Avoid inadvertent casting (to object)
void cref(const refPtr<T>&) = delete;
//- Clear existing and set to (non-const) reference
inline void ref(T& obj) noexcept;
@ -238,6 +268,11 @@ public:
// The pointer can be null, which is handled like a clear().
inline void ref(T* p) noexcept;
//- Avoid inadvertent casting (to object or pointer)
void ref(const autoPtr<T>&) = delete;
//- Avoid inadvertent casting (to object)
void ref(const refPtr<T>&) = delete;
//- Swaps the managed object with other.
inline void swap(tmp<T>& other) noexcept;
@ -284,7 +319,7 @@ public:
inline void operator=(T* p);
//- Reset via assignment from literal nullptr
inline void operator=(std::nullptr_t) noexcept;
void operator=(std::nullptr_t) noexcept { reset(nullptr); }
// Housekeeping
@ -307,8 +342,7 @@ public:
// Global Functions
//- Specialized Swap algorithm for tmp.
// Swaps the pointers and types of lhs and rhs. Calls \c lhs.swap(rhs)
//- Specializes the Swap algorithm for tmp (swaps pointers and types).
template<class T>
void Swap(tmp<T>& lhs, tmp<T>& rhs)
{

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2018-2021 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -39,9 +39,8 @@ inline void Foam::tmp<T>::incrCount()
if (ptr_->count() > 1)
{
FatalErrorInFunction
<< "Attempt to create more than 2 tmp's referring to"
" the same object of type "
<< tmp<T>::typeName()
<< "Attempt to create more than 2 tmp's referring to the same"
" object of type tmp<" << typeid(T).name() << '>'
<< abort(FatalError);
}
}
@ -52,23 +51,7 @@ inline void Foam::tmp<T>::incrCount()
template<class T>
inline Foam::word Foam::tmp<T>::typeName()
{
return "tmp<" + word(typeid(T).name()) + '>';
}
template<class T>
template<class... Args>
inline Foam::tmp<T> Foam::tmp<T>::New(Args&&... args)
{
return tmp<T>(new T(std::forward<Args>(args)...));
}
template<class T>
template<class U, class... Args>
inline Foam::tmp<T> Foam::tmp<T>::NewFrom(Args&&... args)
{
return tmp<T>(new U(std::forward<Args>(args)...));
return Foam::word("tmp<" + std::string(typeid(T).name()) + '>', false);
}
@ -96,7 +79,7 @@ inline Foam::tmp<T>::tmp(T* p)
ptr_(p),
type_(PTR)
{
if (p && !p->unique())
if (ptr_ && !ptr_->unique())
{
FatalErrorInFunction
<< "Attempted construction of a "
@ -143,7 +126,7 @@ inline Foam::tmp<T>::tmp(const tmp<T>& rhs)
ptr_(rhs.ptr_),
type_(rhs.type_)
{
if (type_ == PTR)
if (is_pointer())
{
if (ptr_)
{
@ -152,7 +135,7 @@ inline Foam::tmp<T>::tmp(const tmp<T>& rhs)
else
{
FatalErrorInFunction
<< "Attempted copy of a deallocated "
<< "Attempted copy/move of a deallocated "
<< this->typeName()
<< abort(FatalError);
}
@ -166,14 +149,14 @@ inline Foam::tmp<T>::tmp(const tmp<T>& rhs, bool reuse)
ptr_(rhs.ptr_),
type_(rhs.type_)
{
if (type_ == PTR)
if (is_pointer())
{
if (ptr_)
{
if (reuse)
{
rhs.ptr_ = nullptr;
// Note: rhs.type_ already set as PTR
rhs.type_ = PTR;
}
else
{
@ -183,7 +166,7 @@ inline Foam::tmp<T>::tmp(const tmp<T>& rhs, bool reuse)
else
{
FatalErrorInFunction
<< "Attempted copy of a deallocated "
<< "Attempted copy/move of a deallocated "
<< this->typeName()
<< abort(FatalError);
}
@ -191,10 +174,17 @@ inline Foam::tmp<T>::tmp(const tmp<T>& rhs, bool reuse)
}
template<class T>
inline Foam::tmp<T>::tmp(autoPtr<T>&& rhs) noexcept
:
tmp<T>(rhs.release())
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
template<class T>
inline Foam::tmp<T>::~tmp()
inline Foam::tmp<T>::~tmp() noexcept
{
clear();
}
@ -205,14 +195,14 @@ inline Foam::tmp<T>::~tmp()
template<class T>
inline bool Foam::tmp<T>::movable() const noexcept
{
return (type_ == PTR && ptr_ && ptr_->unique());
return (is_pointer() && ptr_ && ptr_->unique());
}
template<class T>
inline const T& Foam::tmp<T>::cref() const
{
if (type_ == PTR && !ptr_)
if (is_pointer() && !ptr_)
{
FatalErrorInFunction
<< this->typeName() << " deallocated"
@ -233,7 +223,7 @@ inline T& Foam::tmp<T>::ref() const
<< this->typeName()
<< abort(FatalError);
}
else if (type_ == PTR && !ptr_)
else if (is_pointer() && !ptr_)
{
FatalErrorInFunction
<< this->typeName() << " deallocated"
@ -261,7 +251,7 @@ inline T* Foam::tmp<T>::ptr() const
<< abort(FatalError);
}
if (type_ == PTR)
if (is_pointer())
{
if (!ptr_->unique())
{
@ -286,7 +276,7 @@ inline T* Foam::tmp<T>::ptr() const
template<class T>
inline void Foam::tmp<T>::clear() const noexcept
{
if (type_ == PTR && ptr_)
if (is_pointer() && ptr_)
{
if (ptr_->unique())
{
@ -313,9 +303,10 @@ inline void Foam::tmp<T>::reset(T* p) noexcept
template<class T>
inline void Foam::tmp<T>::reset(tmp<T>&& other) noexcept
{
// Could also make Fatal with FULLDEBUG
if (&other == this)
{
return; // Self-assignment is a no-op
return; // No self-assignment
}
clear();
@ -330,9 +321,10 @@ inline void Foam::tmp<T>::reset(tmp<T>&& other) noexcept
template<class T>
inline void Foam::tmp<T>::cref(const tmp<T>& other) noexcept
{
// Could also make Fatal with FULLDEBUG
if (&other == this)
{
return; // Self-assignment is a no-op
return; // No self-assignment
}
clear();
@ -397,7 +389,7 @@ inline void Foam::tmp<T>::swap(tmp<T>& other) noexcept
template<class T>
inline const T* Foam::tmp<T>::operator->() const
{
if (type_ == PTR && !ptr_)
if (is_pointer() && !ptr_)
{
FatalErrorInFunction
<< this->typeName() << " deallocated"
@ -418,7 +410,7 @@ inline T* Foam::tmp<T>::operator->()
<< this->typeName()
<< abort(FatalError);
}
else if (type_ == PTR && !ptr_)
else if (is_pointer() && !ptr_)
{
FatalErrorInFunction
<< this->typeName() << " deallocated"
@ -432,18 +424,21 @@ inline T* Foam::tmp<T>::operator->()
template<class T>
inline void Foam::tmp<T>::operator=(const tmp<T>& other)
{
// Could also make Fatal with FULLDEBUG
if (&other == this)
{
return; // Self-assignment is a no-op
return; // No self-assignment
}
clear();
if (other.type_ == PTR)
if (other.is_pointer())
{
ptr_ = other.ptr_;
type_ = PTR;
other.ptr_ = nullptr;
other.type_ = PTR;
if (!ptr_)
{
@ -466,9 +461,10 @@ inline void Foam::tmp<T>::operator=(const tmp<T>& other)
template<class T>
inline void Foam::tmp<T>::operator=(tmp<T>&& other) noexcept
{
// Could also make Fatal with FULLDEBUG
if (&other == this)
{
return; // Self-assignment is a no-op
return; // No self-assignment
}
clear();
@ -503,11 +499,4 @@ inline void Foam::tmp<T>::operator=(T* p)
}
template<class T>
inline void Foam::tmp<T>::operator=(std::nullptr_t) noexcept
{
reset(nullptr);
}
// ************************************************************************* //

View File

@ -1,25 +1,7 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
// Compatibility include. For v2006 and earlier
Typedef
Foam::tmpNrc
Description
Compatibility name. Superseded (JUL-2020) by Foam::refPtr
\*---------------------------------------------------------------------------*/
#ifndef Foam_tmpNrc_H
#define Foam_tmpNrc_H
#ifndef FoamCompat_tmpNrc_H
#define FoamCompat_tmpNrc_H
#include "refPtr.H"
@ -27,6 +9,8 @@ Description
namespace Foam
{
//- Deprecated(2020-07) - use refPtr instead
// \deprecated(2020-07) - use refPtr instead
typedef refPtr tmpNrc;
}