Commit d029f4c5 authored by Mark OLESEN's avatar Mark OLESEN
Browse files

ENH: improved swap/transfer methods for FixedList

- the transfer method was previously a copy

- use std::reverse_iterator adaptors in FixedList
  This greatly reduces the amount of code and now avoids the array-bounds
  warning for FixedList::rend()

- use pointer arithmetic instead of dereferencing the internal array
parent 8fc27e0e
......@@ -25,7 +25,7 @@ Application
Test-FixedList
Description
Simple tests and examples of use of FixedList
Simple tests and examples for FixedList
See also
Foam::FixedList
......@@ -42,47 +42,72 @@ See also
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
template<class T, unsigned Size>
Ostream& printInfo(const FixedList<List<T>, Size>& list)
{
Info<< list << " addresses:";
for (unsigned i = 0; i < Size; ++i)
{
Info<< " " << long(list[i].cdata());
}
Info<< nl;
return Info;
}
int main(int argc, char *argv[])
template<class T, unsigned Size>
Ostream& printInfo
(
const FixedList<List<T>, Size>& list1,
const FixedList<List<T>, Size>& list2
)
{
argList args(argc, argv);
Info<< "llist1:"; printInfo(list1);
Info<< "llist2:"; printInfo(list2);
return Info;
}
if (false)
{
FixedList<string, 1> ident;
auto iter = ident.begin();
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
Info << iter->size() << endl;
int main(int argc, char *argv[])
{
argList::addBoolOption("assign");
argList::addBoolOption("iter");
argList::addBoolOption("swap");
argList::addBoolOption("default", "reinstate default tests");
argList::addNote("runs default tests or specified ones only");
auto riter = ident.rbegin();
Info << riter->size() << endl;
#include "setRootCase.H"
auto iter2 = ident.rbegin();
// Run default tests, unless only specific tests are requested
const bool defaultTests =
args.found("default") || args.options().empty();
iter2 = iter;
}
if (defaultTests || args.found("iter"))
{
Info<< nl
<< "Test iterators" << nl;
FixedList<label, 15> ident;
std::iota(ident.begin(), ident.end(), 0);
// auto iter = ident.begin();
//
// iter += 5;
// Info << *iter << "< " << endl;
// Info << *iter << "< " << nl;
// iter -= 2;
// Info << *iter << "< " << endl;
// Info << *iter << "< " << nl;
// Don't yet bother with making reverse iterators random access
// auto riter = ident.crbegin();
// riter += 5;
// Info << *riter << "< " << endl;
// Info << *riter << "< " << nl;
// riter += 2;
// Info << *riter << "< " << endl;
// Info << *riter << "< " << nl;
Info<<"Ident:";
forAllConstIters(ident, iter)
......@@ -106,65 +131,121 @@ int main(int argc, char *argv[])
Info<< nl;
}
if (defaultTests || args.found("swap"))
{
FixedList<label, 4> list1{1, 2, 3, 4};
Info<< nl
<< "Test swap" << nl;
FixedList<label, 4> list1{2, 3, 4, 5};
Info<< "list1:" << list1
<< " hash:" << FixedList<label, 4>::Hash<>()(list1) << endl;
<< " hash:" << FixedList<label, 4>::Hash<>()(list1) << nl;
label a[4] = {0, 1, 2, 3};
FixedList<label, 4> list2(a);
Info<< "list2:" << list2
<< " hash:" << FixedList<label, 4>::Hash<>()(list2) << endl;
<< " hash:" << FixedList<label, 4>::Hash<>()(list2) << nl;
// Using FixedList for content too
{
List<FixedList<label, 4>> twolists{list1, list2};
Info<<"List of FixedList: " << flatOutput(twolists) << endl;
Info<<"List of FixedList: " << flatOutput(twolists) << nl;
sort(twolists);
// outer-sort only
Info<<"sorted FixedList : " << flatOutput(twolists) << endl;
Info<<"sorted FixedList : " << flatOutput(twolists) << nl;
}
Info<< "====" << nl
<< "Test swap" << nl;
Info<< "list1: " << list1 << nl
<< "list2: " << list2 << endl;
<< "list2: " << list2 << nl;
// Addresses don't change with swap
Info<< "mem: " << long(list1.data()) << " " << long(list2.data()) << nl;
list1.swap(list2);
Info<< "The swap() method" << endl;
Info<< "The swap() method" << nl;
Info<< "list1: " << list1 << nl
<< "list2: " << list2 << endl;
<< "list2: " << list2 << nl;
Info<< "mem: " << long(list1.data()) << " " << long(list2.data()) << nl;
Swap(list1, list2);
Info<< "The Swap() function" << endl;
Info<< "The Swap() function" << nl;
Info<< "list1: " << list1 << nl
<< "list2: " << list2 << endl;
<< "list2: " << list2 << nl;
Info<< "mem: " << long(list1.data()) << " " << long(list2.data()) << nl;
Info<< "====" << nl;
Info<< nl
<< "Test of swap with other container content" << nl;
FixedList<labelList, 4> llist1;
FixedList<labelList, 4> llist2;
{
label i = 1;
for (auto& item : llist1)
{
item = identity(1 + 1.5*i);
++i;
}
}
Info<< nl
<< "initial lists" << nl;
printInfo(llist1, llist2);
llist2.transfer(llist1);
Info<< nl
<< "After transfer" << nl;
printInfo(llist1, llist2);
llist2.swap(llist1);
Info<< nl
<< "After swap" << nl;
printInfo(llist1, llist2);
llist2 = llist1;
Info<< nl
<< "After copy assignment" << nl;
printInfo(llist1, llist2);
llist2 = std::move(llist1);
Info<< nl
<< "After move assignment" << nl;
printInfo(llist1, llist2);
}
Info<< nl
<< "Test construct and assignment" << nl;
List<label> list3{0, 1, 2, 3};
FixedList<label, 4> list4(list3.begin(), list3.end());
Info<< "list3: " << list3 << nl
<< "list4: " << list4 << endl;
<< "list4: " << list4 << nl;
list4 = {1, 2, 3, 5};
Info<< "list4: " << list4 << nl;
FixedList<label, 5> list5{0, 1, 2, 3, 4};
Info<< "list5: " << list5 << endl;
Info<< "list5: " << list5 << nl;
List<FixedList<label, 2>> list6{{0, 1}, {2, 3}};
Info<< "list6: " << list6 << endl;
Info<< "list6: " << list6 << nl;
if (Pstream::parRun())
{
if (Pstream::myProcNo() != Pstream::masterNo())
{
Serr<< "slave sending to master "
<< Pstream::masterNo() << endl;
<< Pstream::masterNo() << nl;
OPstream toMaster
(
......
......@@ -52,13 +52,6 @@ Foam::label Foam::FixedList<T, Size>::find
}
template<class T, unsigned Size>
void Foam::FixedList<T, Size>::swap(FixedList<T, Size>& lst)
{
Foam::Swap(v_, lst.v_);
}
template<class T, unsigned Size>
void Foam::FixedList<T, Size>::moveFirst(const label i)
{
......@@ -112,72 +105,74 @@ void Foam::FixedList<T, Size>::swapLast(const label i)
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class T, unsigned Size>
bool Foam::FixedList<T, Size>::operator==(const FixedList<T, Size>& a) const
bool Foam::FixedList<T, Size>::operator==(const FixedList<T, Size>& list) const
{
bool equal = true;
List_CONST_ACCESS(T, (*this), vp);
List_CONST_ACCESS(T, (a), ap);
List_CONST_ACCESS(T, *this, lhs);
List_CONST_ACCESS(T, (list), rhs);
// List sizes are identical by definition (template parameter)
for (unsigned i = 0; i < Size; ++i)
{
equal = (vp[i] == ap[i]);
if (!equal) break;
if (!(lhs[i] == rhs[i]))
{
return false;
}
}
return equal;
// Contents appear to be identical.
return true;
}
template<class T, unsigned Size>
bool Foam::FixedList<T, Size>::operator!=(const FixedList<T, Size>& a) const
bool Foam::FixedList<T, Size>::operator<(const FixedList<T, Size>& list) const
{
return !operator==(a);
}
template<class T, unsigned Size>
bool Foam::FixedList<T, Size>::operator<(const FixedList<T, Size>& a) const
{
List_CONST_ACCESS(T, *this, ptr1);
List_CONST_ACCESS(T, a, ptr2);
List_CONST_ACCESS(T, *this, lhs);
List_CONST_ACCESS(T, (list), rhs);
// List sizes are identical by definition (template parameter)
for (unsigned i=0; i<Size; ++i)
{
if (ptr1[i] < ptr2[i])
if (lhs[i] < rhs[i])
{
return true;
}
else if (ptr1[i] > ptr2[i])
else if (rhs[i] < lhs[i])
{
return false;
}
}
// Contents look to be identical.
// The sizes are identical by definition (template parameter)
// Contents appear to be identical.
return false;
}
template<class T, unsigned Size>
bool Foam::FixedList<T, Size>::operator>(const FixedList<T, Size>& a) const
bool Foam::FixedList<T, Size>::operator!=(const FixedList<T, Size>& list) const
{
return !operator==(list);
}
template<class T, unsigned Size>
bool Foam::FixedList<T, Size>::operator>(const FixedList<T, Size>& list) const
{
return a.operator<(*this);
return list.operator<(*this);
}
template<class T, unsigned Size>
bool Foam::FixedList<T, Size>::operator<=(const FixedList<T, Size>& a) const
bool Foam::FixedList<T, Size>::operator<=(const FixedList<T, Size>& list) const
{
return !operator>(a);
return !list.operator<(*this);
}
template<class T, unsigned Size>
bool Foam::FixedList<T, Size>::operator>=(const FixedList<T, Size>& a) const
bool Foam::FixedList<T, Size>::operator>=(const FixedList<T, Size>& list) const
{
return !operator<(a);
return !operator<(list);
}
......
......@@ -47,6 +47,7 @@ SourceFiles
#include <type_traits>
#include <initializer_list>
#include <iterator>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
......@@ -95,6 +96,42 @@ protected:
public:
// STL type definitions
//- The value type the FixedList contains
typedef T value_type;
//- The pointer type for non-const access to value_type items
typedef T* pointer;
//- The pointer type for const access to value_type items
typedef const T* const_pointer;
//- The type used for storing into value_type objects
typedef T& reference;
//- The type used for reading from constant value_type objects.
typedef const T& const_reference;
//- Random access iterator for traversing FixedList
typedef T* iterator;
//- Random access iterator for traversing FixedList
typedef const T* const_iterator;
//- The type to represent the size of a FixedList
typedef label size_type;
//- The difference between iterator objects
typedef label difference_type;
//- Reverse iterator (non-const access)
typedef std::reverse_iterator<iterator> reverse_iterator;
//- Reverse iterator (const access)
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
//- Hashing function class.
// Use Hasher directly for contiguous data. Otherwise hash incrementally.
template<class HashT=Hash<T>>
......@@ -102,7 +139,7 @@ public:
{
inline unsigned operator()
(
const FixedList<T, Size>&,
const FixedList<T, Size>& lst,
unsigned seed = 0
) const;
};
......@@ -117,7 +154,7 @@ public:
// Constructors
//- Null constructor
inline FixedList();
inline FixedList() = default;
//- Construct from value
explicit inline FixedList(const T& val);
......@@ -128,7 +165,8 @@ public:
//- Copy constructor
inline FixedList(const FixedList<T, Size>& lst);
//- Move constructor
//- Move construct by using move assignment for the individual
//- list elements
inline FixedList(FixedList<T, Size>&& lst);
//- Construct given begin/end iterators
......@@ -227,11 +265,11 @@ public:
//- Dummy resize function
// needed to make FixedList consistent with List
inline void resize(const label s);
inline void resize(const label n);
//- Dummy setSize function
// needed to make FixedList consistent with List
inline void setSize(const label s);
inline void setSize(const label n);
//- Move element to the first position.
void moveFirst(const label i);
......@@ -245,9 +283,9 @@ public:
//- Swap element with the last element.
void swapLast(const label i);
//- Copy (not transfer) the argument contents
// needed to make FixedList consistent with List
void transfer(const FixedList<T, Size>& lst);
//- Transfer by swapping using a move assignment for the content
//- of the individual list elements
inline void transfer(FixedList<T, Size>& lst);
// Member operators
......@@ -280,29 +318,7 @@ public:
inline void operator=(FixedList<T, Size>&& lst);
// STL type definitions
//- Type of values the FixedList contains
typedef T value_type;
//- The type used for storing into value_type objects
typedef T& reference;
//- The type used for reading from constant value_type objects.
typedef const T& const_reference;
//- The type that can represent the difference between any two
//- FixedList iterator objects
typedef label difference_type;
//- The type that can represent the size of a FixedList
typedef label size_type;
// STL iterator
//- Random access iterator for traversing FixedList
typedef T* iterator;
// Random access iterator (non-const)
//- Return an iterator to begin traversing the FixedList
inline iterator begin();
......@@ -311,10 +327,7 @@ public:
inline iterator end();
// STL const_iterator
//- Random access iterator for traversing FixedList
typedef const T* const_iterator;
// Random access iterator (const)
//- Return const_iterator to begin traversing the constant FixedList
inline const_iterator cbegin() const;
......@@ -329,86 +342,7 @@ public:
inline const_iterator end() const;
// Reverse iterators
//- Generic const/non-const reverse iterator
template<bool Const>
class reverse_iterator_base
{
public:
//- The const/non-const type for entries
typedef typename std::conditional
<Const, const T, T>::type value_type;
//- A pointer to a const/non-const entry
typedef value_type* pointer;
//- A reference to a const/non-const entry
typedef value_type& reference;
private:
//- The element pointer
pointer ptr_;
public:
//- Construct null or from list element pointer
inline reverse_iterator_base(pointer ptr = nullptr)
:
ptr_(ptr)
{}
//- Copy construct
inline reverse_iterator_base(const reverse_iterator_base& iter)
:
ptr_(iter.ptr_)
{}
//- Reverse increment
inline void operator++()
{
--ptr_;
}
//- Reverse increment
inline reverse_iterator_base operator++(int)
{
reverse_iterator_base old(*this);
--ptr_;
return old;
}
//- Dereference iterator
reference operator*() const
{
return *ptr_;
}
//- Dereference iterator
pointer operator->() const
{
return ptr_;
}
//- Equality
bool operator==(const reverse_iterator_base& iter) const
{
return ptr_ == iter.ptr_;
}
//- inequality
bool operator!=(const reverse_iterator_base& iter) const
{
return ptr_ != iter.ptr_;
}
};
//- STL reverse_iterator
typedef reverse_iterator_base<false> reverse_iterator;
// Reverse iterator (non-const)
//- Return reverse_iterator to begin reverse traversing the FixedList
inline reverse_iterator rbegin();
......@@ -417,8 +351,7 @@ public:
inline reverse_iterator rend();
//- STL const reverse iterator
typedef reverse_iterator_base<true> const_reverse_iterator;
// Reverse iterator (const)
//- Return const_reverse_iterator to begin reverse traversing FixedList
inline const_reverse_iterator crbegin() const;
......@@ -444,31 +377,31 @@ public:
//- Always false since zero-sized FixedList is compile-time disabled.
inline bool empty() const;
//- Swap content with another FixedList of the same type.
void swap(FixedList<T, Size>& lst);
//- Swap lists by swapping the content of the individual list elements
inline void swap(FixedList<T, Size>& lst);
// STL member operators
//- Equality operation on FixedLists of the same type.
// Returns true when the FixedLists are element-wise equal
// (using FixedList::value_type::operator==). Takes linear time