Commit 2f32b586 authored by Mark OLESEN's avatar Mark OLESEN
Browse files

ENH: PtrList, UPtrList cleanup

- rationalize iterators, reduce code duplication,
  improve assignment behaviour, moveable construct and assignment.
parent cc5f30f2
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -21,10 +21,8 @@ License
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application
Description
Test behaviour of UPtrList, PtrList
\*---------------------------------------------------------------------------*/
#include "OSspecific.H"
......@@ -102,13 +100,13 @@ int main(int argc, char *argv[])
forAllIters(llist1, it)
{
Info<< typeid(*it).name() << endl;
Info<< "reversed: " << *it << endl;
Info<< typeid(*it).name() << nl
<< "reversed: " << *it << endl;
}
for (const auto& it : llist1)
{
Info<< typeid(it).name() << endl;
Info<< "for-: " << it << endl;
Info<< typeid(it).name() << nl
<< "for-: " << it << endl;
}
}
......@@ -127,9 +125,10 @@ int main(int argc, char *argv[])
listApp.append(new Scalar(1.3*i));
}
Info<<"list1: " << list1 << endl;
Info<<"list2: " << list2 << endl;
Info<<"listApp: " << listApp << endl;
Info<< nl
<<"list1: " << list1 << nl
<<"list2: " << list2 << nl
<<"list-appended: " << listApp << endl;
Info<<"indirectly delete some items via set(.., 0) :" << endl;
for (label i = 0; i < 3; i++)
......@@ -140,8 +139,8 @@ int main(int argc, char *argv[])
Info<<"transfer list2 -> list1:" << endl;
list1.transfer(list2);
Info<<"list1: " << list1 << endl;
Info<<"list2: " << list2 << endl;
Info<<"list1: " << list1 << nl
<<"list2: " << list2 << endl;
Info<<"indirectly delete some items via setSize :" << endl;
list1.setSize(4);
......@@ -151,16 +150,71 @@ int main(int argc, char *argv[])
PtrList<Scalar> list3(list1.xfer());
Info<< "Transferred via the xfer() method" << endl;
Info<<"list1: " << list1 << endl;
Info<<"list2: " << list2 << endl;
Info<<"list3: " << list3 << endl;
Info<<"list1: " << list1 << nl
<<"list2: " << list2 << nl
<<"list3: " << list3 << endl;
Info<<"Move construct:" << endl;
PtrList<Scalar> list4(std::move(list3));
Info<<"list3: " << list3 << nl
<<"list4: " << list4 << endl;
Info<<"Move assign:" << endl;
list3 = std::move(list4);
Info<<"list3: " << list3 << nl
<<"list4: " << list4 << endl;
Info<<"UPtrList from PtrList" << nl;
UPtrList<Scalar> ulist1(list3);
Info<<"ulist1: " << ulist1 << nl;
Info<<"Move construct:" << endl;
UPtrList<Scalar> ulist2(std::move(ulist1));
Info<<"ulist1: " << ulist1 << nl
<<"ulist2: " << ulist2 << nl;
Info<<"Copy assign:" << endl;
ulist1 = ulist2;
Info<<"ulist1: " << ulist1 << nl
<<"ulist2: " << ulist2 << nl;
Info<<"Move assign:" << endl;
ulist1 = std::move(ulist2);
Info<<"ulist1: " << ulist1 << nl
<<"ulist2: " << ulist2 << nl;
// Test iterator random access
{
auto iter1 = ulist1.begin();
auto iter2 = iter1 + 3;
Info<<"begin:" << *iter1 << " (+3):" << *iter2 << nl;
Info<< "diff= " << (iter1 - iter2) << nl;
Info<< "iter[2]=" << iter1[2] << nl;
Info<< "iter1 < iter2 : " << (iter1 < iter2) << nl;
Info<< "iter1 >= iter2 : " << (iter1 >= iter2) << nl;
}
PtrList<plane> planes;
planes.append(new plane(vector::one, vector::one));
planes.append(new plane(vector(1,2,3), vector::one));
forAll(planes, p)
Info<< "plane " << planes[p] << endl;
Info<< nl << "appended values" << nl;
for (const plane& p : planes)
{
Info<< " plane " << p << endl;
}
Info<< nl << "Done." << endl;
return 0;
......
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -29,40 +29,30 @@ License
// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
template<class T>
Foam::PtrList<T>::PtrList()
Foam::PtrList<T>::PtrList(const PtrList<T>& lst)
:
UPtrList<T>()
{}
template<class T>
Foam::PtrList<T>::PtrList(const label len)
:
UPtrList<T>(len)
{}
template<class T>
Foam::PtrList<T>::PtrList(const PtrList<T>& a)
:
UPtrList<T>(a.size())
UPtrList<T>(lst.size())
{
forAll(*this, i)
const label len = this->size();
for (label i=0; i<len; ++i)
{
this->ptrs_[i] = (a[i]).clone().ptr();
this->ptrs_[i] = (lst[i]).clone().ptr();
}
}
template<class T>
template<class CloneArg>
Foam::PtrList<T>::PtrList(const PtrList<T>& a, const CloneArg& cloneArg)
Foam::PtrList<T>::PtrList(const PtrList<T>& lst, const CloneArg& cloneArg)
:
UPtrList<T>(a.size())
UPtrList<T>(lst.size())
{
forAll(*this, i)
const label len = this->size();
for (label i=0; i<len; ++i)
{
this->ptrs_[i] = (a[i]).clone(cloneArg).ptr();
this->ptrs_[i] = (lst[i]).clone(cloneArg).ptr();
}
}
......@@ -75,34 +65,31 @@ Foam::PtrList<T>::PtrList(const Xfer<PtrList<T>>& lst)
template<class T>
Foam::PtrList<T>::PtrList(PtrList<T>& a, bool reuse)
Foam::PtrList<T>::PtrList(PtrList<T>& lst, bool reuse)
:
UPtrList<T>(a, reuse)
UPtrList<T>(lst, reuse)
{
if (!reuse)
{
forAll(*this, i)
const label len = this->size();
for (label i=0; i<len; ++i)
{
this->ptrs_[i] = (a[i]).clone().ptr();
this->ptrs_[i] = (lst[i]).clone().ptr();
}
}
}
template<class T>
Foam::PtrList<T>::PtrList(const SLPtrList<T>& sll)
Foam::PtrList<T>::PtrList(const SLPtrList<T>& lst)
:
UPtrList<T>(sll.size())
UPtrList<T>(lst.size())
{
if (sll.size())
if (lst.size())
{
label i = 0;
for
(
typename SLPtrList<T>::const_iterator iter = sll.cbegin();
iter != sll.cend();
++iter
)
for (auto iter = lst.cbegin(); iter != lst.cend(); ++iter)
{
this->ptrs_[i++] = (*iter).clone().ptr();
}
......@@ -115,7 +102,10 @@ Foam::PtrList<T>::PtrList(const SLPtrList<T>& sll)
template<class T>
Foam::PtrList<T>::~PtrList()
{
forAll(*this, i)
const label len = this->size();
// Free old pointers
for (label i=0; i<len; ++i)
{
if (this->ptrs_[i])
{
......@@ -127,53 +117,12 @@ Foam::PtrList<T>::~PtrList()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T>
void Foam::PtrList<T>::setSize(const label newSize)
{
if (newSize < 0)
{
FatalErrorInFunction
<< "bad set size " << newSize
<< " for type " << typeid(T).name()
<< abort(FatalError);
}
label oldSize = this->size();
if (newSize == 0)
{
clear();
}
else if (newSize < oldSize)
{
label i;
for (i=newSize; i<oldSize; i++)
{
if (this->ptrs_[i])
{
delete this->ptrs_[i];
}
}
this->ptrs_.setSize(newSize);
}
else // newSize > oldSize
{
this->ptrs_.setSize(newSize);
label i;
for (i=oldSize; i<newSize; i++)
{
this->ptrs_[i] = nullptr;
}
}
}
template<class T>
void Foam::PtrList<T>::clear()
{
forAll(*this, i)
const label len = this->size();
for (label i=0; i<len; ++i)
{
if (this->ptrs_[i])
{
......@@ -181,109 +130,82 @@ void Foam::PtrList<T>::clear()
}
}
this->ptrs_.clear();
}
template<class T>
void Foam::PtrList<T>::transfer(PtrList<T>& a)
{
clear();
this->ptrs_.transfer(a.ptrs_);
UPtrList<T>::clear();
}
template<class T>
void Foam::PtrList<T>::reorder(const labelUList& oldToNew)
void Foam::PtrList<T>::setSize(const label newLen)
{
if (oldToNew.size() != this->size())
if (newLen <= 0)
{
FatalErrorInFunction
<< "Size of map (" << oldToNew.size()
<< ") not equal to list size (" << this->size()
<< ") for type " << typeid(T).name()
<< abort(FatalError);
clear();
return;
}
List<T*> newPtrs_(this->ptrs_.size(), reinterpret_cast<T*>(0));
forAll(*this, i)
const label oldLen = this->size();
if (newLen < oldLen)
{
const label newI = oldToNew[i];
if (newI < 0 || newI >= this->size())
// Truncate - free old pointers
for (label i=newLen; i<oldLen; ++i)
{
FatalErrorInFunction
<< "Illegal index " << newI << nl
<< "Valid indices are 0.." << this->size()-1
<< " for type " << typeid(T).name()
<< abort(FatalError);
if (this->ptrs_[i])
{
delete this->ptrs_[i];
}
}
if (newPtrs_[newI])
{
FatalErrorInFunction
<< "reorder map is not unique; element " << newI
<< " already set for type " << typeid(T).name()
<< abort(FatalError);
}
newPtrs_[newI] = this->ptrs_[i];
this->ptrs_.setSize(newLen);
}
forAll(newPtrs_, i)
else if (newLen > oldLen)
{
if (!newPtrs_[i])
{
FatalErrorInFunction
<< "Element " << i << " not set after reordering with type "
<< typeid(T).name() << nl << abort(FatalError);
}
// Extend - new elements initialized to nullptr
this->ptrs_.setSize(newLen, reinterpret_cast<T*>(0));
}
this->ptrs_.transfer(newPtrs_);
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class T>
void Foam::PtrList<T>::operator=(const PtrList<T>& a)
void Foam::PtrList<T>::operator=(const PtrList<T>& lst)
{
if (this == &a)
if (this == &lst)
{
FatalErrorInFunction
<< "attempted assignment to self for type " << typeid(T).name()
<< abort(FatalError);
}
if (this->size() == 0)
{
setSize(a.size());
const label oldLen = this->size();
const label newLen = lst.size();
forAll(*this, i)
{
this->ptrs_[i] = (a[i]).clone().ptr();
}
}
else if (a.size() == this->size())
// Truncate (frees old pointers) or extend the length
setSize(newLen);
if (newLen < oldLen)
{
forAll(*this, i)
// Copy values for existing entries
for (label i=0; i<newLen; ++i)
{
(*this)[i] = a[i];
(*this)[i] = lst[i];
}
}
else
{
FatalErrorInFunction
<< "bad size: " << a.size()
<< " for type " << typeid(T).name()
<< abort(FatalError);
// Copy values for existing entries
for (label i=0; i<oldLen; ++i)
{
(*this)[i] = lst[i];
}
// Clone pointers for new entries
for (label i=oldLen; i<newLen; ++i)
{
this->ptrs_[i] = (lst[i]).clone().ptr();
}
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "PtrListIO.C"
// ************************************************************************* //
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -25,11 +25,12 @@ Class
Foam::PtrList
Description
A templated 1D list of pointers to objects of type \<T\>, where the
size of the array is known and used for subscript bounds checking, etc.
A list of pointers to objects of type \<T\>, with allocation/deallocation
management of the pointers.
The operator[] returns a reference to the object, not the pointer.
The element operator [] returns a reference to the object rather than a
pointer.
See Also
Foam::PtrList
SourceFiles
PtrListI.H
......@@ -81,27 +82,30 @@ public:
// Constructors
//- Null Constructor
PtrList();
//- Construct null
PtrList() = default;
//- Construct with specified size, each element initialized to nullptr
explicit inline PtrList(const label nElem);
//- Construct with size specified
explicit PtrList(const label len);
//- Copy construct using 'clone()' method on each element
PtrList(const PtrList<T>& lst);
//- Copy constructor, using 'clone()' method on each element
PtrList(const PtrList<T>& a);
//- Move construct
inline PtrList(PtrList<T>&& lst);
//- Copy constructor with additional argument for clone
//- Copy construct with additional argument for 'clone()'
template<class CloneArg>
PtrList(const PtrList<T>& a, const CloneArg& cloneArg);
PtrList(const PtrList<T>& lst, const CloneArg& cloneArg);
//- Construct by transferring the parameter contents
PtrList(const Xfer<PtrList<T>>& lst);
//- Construct as copy or re-use as specified
PtrList(PtrList<T>& a, bool reuse);
PtrList(PtrList<T>& lst, bool reuse);
//- Construct as copy of SLPtrList<T>
explicit PtrList(const SLPtrList<T>& sll);
explicit PtrList(const SLPtrList<T>& lst);
//- Construct from Istream using given Istream constructor class
template<class INew>
......@@ -115,62 +119,62 @@ public:
~PtrList();
// Member functions
// Member Functions
// Edit
//- Clear the PtrList. Set size to zero and delete allocated entries
void clear();
//- Reset size of PtrList. If extending the PtrList, new entries are
// set to nullptr. If truncating the PtrList, removed entries are
// deleted
void setSize(const label);
//- Reset size of PtrList.
// New entries are initialized to nullptr, removed entries are deleted
void setSize(const label newLen);
//- Alias for setSize(const label)
inline void resize(const label);
//- Reset size of PtrList.
// New entries are initialized to nullptr, removed entries are deleted
inline void resize(const label newLen);
//- Clear the PtrList, i.e. set size to zero deleting all the
// allocated entries
void clear();
//- Append an element at the end of the list
using UPtrList<T>::append;
//- Append an element at the end of the list
inline void append(T*);
inline void append(const autoPtr<T>&);
inline void append(const tmp<T>&);
//- Append an element at the end of the list
inline void append(const autoPtr<T>& aptr);
//- Transfer the contents of the argument PtrList into this PtrList
// and annul the argument list
void transfer(PtrList<T>&);
//- Append an element at the end of the list
inline void append(const tmp<T>& tptr);
//- Transfer contents to the Xfer container
inline Xfer<PtrList<T>> xfer();
//- Transfer into this list and annul the argument list
inline void transfer(PtrList<T>& lst);
//- Is element set
inline bool set(const label) const;
//- Transfer contents to the Xfer container
inline Xfer<PtrList<T>> xfer();
//- Set element to given T* and return old element (can be nullptr)
inline autoPtr<T> set(const label, T*);
//- Return true if element is set (ie, not a nullptr)
inline bool set(const label i) const;
//- Set element to given autoPtr<T> and return old element
inline autoPtr<T> set(const label, const autoPtr<T>&);
//- Set element to given pointer and return old element (can be null)
inline autoPtr<T> set(const label i, T* ptr);
//- Set element to given tmp<T> and return old element
inline autoPtr<T> set(const label, const tmp<T>&);
//- Set element to given autoPtr and return old element
inline autoPtr<T> set(const label i, const autoPtr<T>& aptr);
//- Reorders elements. Ordering does not have to be done in
// ascending or descending order. Reordering has to be unique.
// (is shuffle)
void reorder(const labelUList&);
//- Set element to given tmp and return old element
inline autoPtr<T> set(const label i, const tmp<T>& tptr);