Commit b0c88dff authored by Mark Olesen's avatar Mark Olesen Committed by Andrew Heather
Browse files

ENH: treat self-assignment as no-op instead of a Fatal (#1473)

- this can help if using std algorithms that return a const reference
  such as std::min() does.
parent 883752cf
......@@ -89,19 +89,16 @@ Foam::CLASSNAME::~CLASSNAME()
void Foam::CLASSNAME::operator=(const CLASSNAME& rhs)
{
// Check for assignment to self
if (this == &rhs)
{
FatalErrorInFunction
<< "Attempted assignment to self"
<< abort(FatalError);
return; // Self-assignment is a no-op
}
}
// * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// ************************************************************************* //
......@@ -102,12 +102,9 @@ void Foam::CLASSNAME<TemplateArgument>::operator=
const CLASSNAME<TemplateArgument>& rhs
)
{
// Check for assignment to self
if (this == &rhs)
{
FatalErrorInFunction
<< "Attempted assignment to self"
<< abort(FatalError);
return; // Self-assignment is a no-op
}
}
......
......@@ -126,7 +126,11 @@ inline bool Foam::regExpPosix::search(const std::string& text) const
inline void Foam::regExpPosix::swap(regExpPosix& rgx)
{
std::swap(preg_, rgx.preg_);
if (this != &rgx)
{
// Self-swap is a no-op
std::swap(preg_, rgx.preg_);
}
}
......
......@@ -320,6 +320,7 @@ inline void Foam::PackedList<Width>::reference::operator=
const reference& other
)
{
// Accepts self-assignment
this->set(other.get());
}
......@@ -556,6 +557,11 @@ inline std::streamsize Foam::PackedList<Width>::byteSize() const
template<unsigned Width>
inline void Foam::PackedList<Width>::swap(PackedList<Width>& rhs)
{
if (this == &rhs)
{
return; // Self-swap is a no-op
}
blocks_.swap(rhs.blocks_);
Foam::Swap(size_, rhs.size_);
}
......@@ -564,8 +570,12 @@ inline void Foam::PackedList<Width>::swap(PackedList<Width>& rhs)
template<unsigned Width>
inline void Foam::PackedList<Width>::transfer(PackedList<Width>& rhs)
{
blocks_.transfer(rhs.blocks_);
if (this == &rhs)
{
return; // Self-assignment is a no-op
}
blocks_.transfer(rhs.blocks_);
size_ = rhs.size_;
rhs.size_ = 0;
}
......
......@@ -197,6 +197,7 @@ inline void Foam::bitSet::reference::operator=
const reference& other
)
{
// Accepts self-assignment
set(other.get());
}
......
......@@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2012-2015 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -170,12 +171,9 @@ void Foam::Circulator<ContainerType>::operator=
const Circulator<ContainerType>& rhs
)
{
// Check for assignment to self
if (this == &rhs)
{
FatalErrorInFunction
<< "Attempted assignment to self"
<< abort(FatalError);
return; // Self-assignment is a no-op
}
begin_ = rhs.begin_;
......
......@@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2012-2015 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -175,12 +176,9 @@ void Foam::ConstCirculator<ContainerType>::operator=
const ConstCirculator<ContainerType>& rhs
)
{
// Check for assignment to self
if (this == &rhs)
{
FatalErrorInFunction
<< "Attempted assignment to self"
<< abort(FatalError);
return; // Self-assignment is a no-op
}
begin_ = rhs.begin_;
......
......@@ -232,6 +232,11 @@ void Foam::DictionaryBase<IDLListType, T>::transfer
DictionaryBase<IDLListType, T>& dict
)
{
if (this == &dict)
{
return; // Self-assignment is a no-op
}
IDLListType::transfer(dict);
hashedTs_.transfer(dict.hashedTs_);
}
......@@ -247,9 +252,7 @@ void Foam::DictionaryBase<IDLListType, T>::operator=
{
if (this == &dict)
{
FatalErrorInFunction
<< "attempted assignment to self"
<< abort(FatalError);
return; // Self-assignment is a no-op
}
IDLListType::operator=(dict);
......
......@@ -149,9 +149,7 @@ void Foam::HashPtrTable<T, Key, Hash>::operator=
{
if (this == &rhs)
{
FatalErrorInFunction
<< "attempted copy assignment to self"
<< abort(FatalError);
return; // Self-assignment is a no-op
}
this->clear();
......@@ -179,9 +177,7 @@ void Foam::HashPtrTable<T, Key, Hash>::operator=
{
if (this == &rhs)
{
FatalErrorInFunction
<< "attempted move assignment to self"
<< abort(FatalError);
return; // Self-assignment is a no-op
}
this->clear();
......
......@@ -656,6 +656,11 @@ void Foam::HashTable<T, Key, Hash>::clearStorage()
template<class T, class Key, class Hash>
void Foam::HashTable<T, Key, Hash>::swap(HashTable<T, Key, Hash>& rhs)
{
if (this == &rhs)
{
return; // Self-swap is a no-op
}
Foam::Swap(size_, rhs.size_);
Foam::Swap(capacity_, rhs.capacity_);
Foam::Swap(table_, rhs.table_);
......@@ -665,6 +670,11 @@ void Foam::HashTable<T, Key, Hash>::swap(HashTable<T, Key, Hash>& rhs)
template<class T, class Key, class Hash>
void Foam::HashTable<T, Key, Hash>::transfer(HashTable<T, Key, Hash>& rhs)
{
if (this == &rhs)
{
return; // Self-assignment is a no-op
}
clear();
swap(rhs);
}
......@@ -759,12 +769,9 @@ void Foam::HashTable<T, Key, Hash>::operator=
const HashTable<T, Key, Hash>& rhs
)
{
// Check for assignment to self
if (this == &rhs)
{
FatalErrorInFunction
<< "attempted assignment to self"
<< abort(FatalError);
return; // Self-assignment is a no-op
}
if (!capacity_)
......@@ -813,12 +820,9 @@ void Foam::HashTable<T, Key, Hash>::operator=
HashTable<T, Key, Hash>&& rhs
)
{
// Check for assignment to self
if (this == &rhs)
{
FatalErrorInFunction
<< "attempted assignment to self"
<< abort(FatalError);
return; // Self-assignment is a no-op
}
transfer(rhs);
......
......@@ -185,6 +185,11 @@ inline void Foam::DLListBase::clear()
inline void Foam::DLListBase::swap(DLListBase& lst)
{
if (this == &lst)
{
return; // Self-swap is a no-op
}
std::swap(first_, lst.first_);
std::swap(last_, lst.last_);
std::swap(size_, lst.size_);
......@@ -193,6 +198,11 @@ inline void Foam::DLListBase::swap(DLListBase& lst)
inline void Foam::DLListBase::transfer(DLListBase& lst)
{
if (this == &lst)
{
return; // Self-assignment is a no-op
}
first_ = lst.first_;
last_ = lst.last_;
size_ = lst.size_;
......
......@@ -143,6 +143,11 @@ inline void Foam::SLListBase::clear()
inline void Foam::SLListBase::swap(SLListBase& lst)
{
if (this == &lst)
{
return; // Self-swap is a no-op
}
std::swap(last_, lst.last_);
std::swap(size_, lst.size_);
}
......@@ -150,6 +155,11 @@ inline void Foam::SLListBase::swap(SLListBase& lst)
inline void Foam::SLListBase::transfer(SLListBase& lst)
{
if (this == &lst)
{
return; // Self-assignment is a no-op
}
last_ = lst.last_;
size_ = lst.size_;
......
......@@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -203,6 +204,11 @@ void Foam::CompactListList<T, Container>::swap
CompactListList<T, Container>& lst
)
{
if (this == &lst)
{
return; // Self-swap is a no-op
}
Foam::Swap(size_, lst.size_);
offsets_.swap(lst.offsets_);
m_.swap(lst.m_);
......@@ -215,6 +221,11 @@ void Foam::CompactListList<T, Container>::transfer
CompactListList<T, Container>& lst
)
{
if (this == &lst)
{
return; // Self-assignment is a no-op
}
size_ = lst.size_;
offsets_.transfer(lst.offsets_);
m_.transfer(lst.m_);
......
......@@ -303,6 +303,11 @@ inline void Foam::CompactListList<T, Container>::operator=
const CompactListList<T, Container>& lst
)
{
if (this == &lst)
{
return; // Self-assignment is a no-op
}
size_ = lst.size_;
offsets_ = lst.offsets_,
m_ = lst.m_;
......@@ -315,6 +320,11 @@ inline void Foam::CompactListList<T, Container>::operator=
CompactListList<T, Container>&& lst
)
{
if (this == &lst)
{
return; // Self-assignment is a no-op
}
transfer(lst);
}
......
......@@ -6,6 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -557,12 +558,9 @@ void Foam::Distribution<Type>::operator=
const Distribution<Type>& rhs
)
{
// Check for assignment to self
if (this == &rhs)
{
FatalErrorInFunction
<< "Attempted assignment to self"
<< abort(FatalError);
return; // Self-assignment is a no-op
}
List<List<scalar>>::operator=(rhs);
......
......@@ -397,6 +397,11 @@ inline void Foam::DynamicList<T, SizeMin>::swap
DynamicList<T, AnySizeMin>& lst
)
{
if (this == &lst)
{
return; // Self-swap is a no-op
}
DynamicList<T, SizeMin>& cur = *this;
// Make addressable size identical to the allocated capacity
......@@ -434,6 +439,11 @@ Foam::DynamicList<T, SizeMin>::transfer
DynamicList<T, AnySizeMin>& lst
)
{
if (this == &lst)
{
return; // Self-assignment is a no-op
}
// Take over storage as-is (without shrink, without using SizeMin)
// clear addressing and storage for old lst.
capacity_ = lst.capacity();
......@@ -793,8 +803,7 @@ inline void Foam::DynamicList<T, SizeMin>::operator=
{
if (this == &lst)
{
FatalErrorInFunction
<< "Attempted assignment to self" << abort(FatalError);
return; // Self-assignment is a no-op
}
assignDynList(lst);
......@@ -808,6 +817,11 @@ inline void Foam::DynamicList<T, SizeMin>::operator=
const DynamicList<T, SizeMin2>& lst
)
{
if (this == &lst)
{
return; // Self-assignment is a no-op
}
assignDynList(lst);
}
......@@ -852,8 +866,7 @@ inline void Foam::DynamicList<T, SizeMin>::operator=
{
if (this == &lst)
{
FatalErrorInFunction
<< "Attempted assignment to self" << abort(FatalError);
return; // Self-assignment is a no-op
}
clear();
......@@ -868,6 +881,11 @@ inline void Foam::DynamicList<T, SizeMin>::operator=
DynamicList<T, SizeMin2>&& lst
)
{
if (this == &lst)
{
return; // Self-assignment is a no-op
}
clear();
transfer(lst);
}
......@@ -887,7 +905,11 @@ inline void Foam::DynamicList<T, SizeMin>::operator=
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
template<class T, int SizeMin1, int SizeMin2>
inline void Foam::Swap(DynamicList<T, SizeMin1>& a, DynamicList<T, SizeMin2>& b)
inline void Foam::Swap
(
DynamicList<T, SizeMin1>& a,
DynamicList<T, SizeMin2>& b
)
{
a.swap(b);
}
......
......@@ -331,6 +331,11 @@ inline void Foam::FixedList<T, N>::setSize(const label n)
template<class T, unsigned N>
inline void Foam::FixedList<T, N>::swap(FixedList<T, N>& list)
{
if (this == &list)
{
return; // Self-swap is a no-op
}
for (unsigned i=0; i<N; ++i)
{
Foam::Swap(v_[i], list.v_[i]);
......@@ -341,6 +346,11 @@ inline void Foam::FixedList<T, N>::swap(FixedList<T, N>& list)
template<class T, unsigned N>
inline void Foam::FixedList<T, N>::transfer(FixedList<T, N>& list)
{
if (this == &list)
{
return; // Self-assignment is a no-op
}
for (unsigned i=0; i<N; ++i)
{
v_[i] = std::move(list[i]);
......@@ -428,6 +438,11 @@ inline void Foam::FixedList<T, N>::operator=(const T& val)
template<class T, unsigned N>
inline void Foam::FixedList<T, N>::operator=(const FixedList<T, N>& list)
{
if (this == &list)
{
return; // Self-assignment is a no-op
}
for (unsigned i=0; i<N; ++i)
{
v_[i] = list.v_[i];
......@@ -437,6 +452,11 @@ inline void Foam::FixedList<T, N>::operator=(const FixedList<T, N>& list)
template<class T, unsigned N>
inline void Foam::FixedList<T, N>::operator=(FixedList<T, N>&& list)
{
if (this == &list)
{
return; // Self-assignment is a no-op
}
// No significant speedup observed for copy assignment on simple types,
// use move assignment for generality with more complex types
for (unsigned i=0; i<N; ++i)
......
......@@ -435,6 +435,11 @@ void Foam::List<T>::resize(const label newSize, const T& val)
template<class T>
void Foam::List<T>::transfer(List<T>& list)
{
if (this == &list)
{
return; // Self-assignment is a no-op
}
// Clear and swap - could also check for self assignment
clear();
this->size_ = list.size_;
......@@ -472,6 +477,11 @@ void Foam::List<T>::transfer(SortableList<T>& list)
template<class T>
void Foam::List<T>::operator=(const UList<T>& a)
{
if (this == &a)
{
return; // Self-assignment is a no-op
}
reAlloc(a.size_);
const label len = this->size_;
......@@ -505,9 +515,7 @@ void Foam::List<T>::operator=(const List<T>& list)
{
if (this == &list)
{
FatalErrorInFunction
<< "attempted assignment to self"
<< abort(FatalError);
return; // Self-assignment is a no-op
}
operator=(static_cast<const UList<T>&>(list));
......@@ -581,9 +589,7 @@ void Foam::List<T>::operator=(List<T>&& list)
{
if (this == &list)
{
FatalErrorInFunction
<< "attempted assignment to self"
<< abort(FatalError);
return; // Self-assignment is a no-op
}
transfer(list);
......
......@@ -193,7 +193,7 @@ inline void Foam::List<T>::append(const UList<T>& list)
if (this == &list)
{
FatalErrorInFunction
<< "attempted appending to self" << abort(FatalError);
<< "Attempted appending to self" << abort(FatalError);
}
label idx = this->size();
......
......@@ -197,6 +197,11 @@ void Foam::SortableList<T>::partialReverseSort(label n, label start)
template<class T>
void Foam::SortableList<T>::swap(SortableList<T>& lst)
{
if (this == &lst)
{
return; // Self-swap is a no-op
}
List<T>::swap(lst);
indices_.swap(lst.indices_);
}
......@@ -223,6 +228,11 @@ inline void Foam::SortableList<T>::operator=(const UList<T>& lst)
template<class T>
inline void Foam::SortableList<T>::operator=(const SortableList<T>& lst)
{
if (this == &lst)
{
return; // Self-assigment is a no-op
}
List<T>::operator=(lst);
indices_ = lst.indices();
}
......@@ -239,6 +249,11 @@ inline void Foam::SortableList<T>::operator=(List<T>&& lst)
template<class T>
inline void Foam::SortableList<T>::operator=(SortableList<T>&& lst)
{
if (this == &lst)
{
return; // Self-assigment is a no-op
}
clear();
this->swap(lst);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment