From b4703f4a08f42f0ff9b182f38d457be148c92226 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Sun, 4 Mar 2018 21:38:33 +0100
Subject: [PATCH] ENH: pre-cleanup of Xfer class (issue #639)

- This class is largely a pre-C++11 holdover, prior to having movable
  references.

- align internals with autoPtr instead of always unconditionally
  allocating memory. The valid() method can be used to check for a null
  pointer.

- Consolidate into a single file, in anticipation of future removal.
---
 applications/test/xfer1/Make/files   |   3 -
 applications/test/xfer1/Make/options |   0
 applications/test/xfer1/Test-xfer1.C | 233 ---------------------------
 src/OpenFOAM/memory/Xfer/Xfer.H      | 127 +++++++++------
 src/OpenFOAM/memory/Xfer/XferI.H     | 186 ---------------------
 5 files changed, 78 insertions(+), 471 deletions(-)
 delete mode 100644 applications/test/xfer1/Make/files
 delete mode 100644 applications/test/xfer1/Make/options
 delete mode 100644 applications/test/xfer1/Test-xfer1.C
 delete mode 100644 src/OpenFOAM/memory/Xfer/XferI.H

diff --git a/applications/test/xfer1/Make/files b/applications/test/xfer1/Make/files
deleted file mode 100644
index 10a272c0273..00000000000
--- a/applications/test/xfer1/Make/files
+++ /dev/null
@@ -1,3 +0,0 @@
-Test-xfer1.C
-
-EXE = $(FOAM_USER_APPBIN)/Test-xfer1
diff --git a/applications/test/xfer1/Make/options b/applications/test/xfer1/Make/options
deleted file mode 100644
index e69de29bb2d..00000000000
diff --git a/applications/test/xfer1/Test-xfer1.C b/applications/test/xfer1/Test-xfer1.C
deleted file mode 100644
index f1fe7c0674e..00000000000
--- a/applications/test/xfer1/Test-xfer1.C
+++ /dev/null
@@ -1,233 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  |
--------------------------------------------------------------------------------
-License
-    This file is part of OpenFOAM.
-
-    OpenFOAM is free software: you can redistribute it and/or modify it
-    under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
-    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-    for more details.
-
-    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
-
-\*---------------------------------------------------------------------------*/
-
-#include "OSspecific.H"
-
-#include "IOstreams.H"
-#include "labelList.H"
-#include "DynamicList.H"
-#include "face.H"
-#include "pointField.H"
-#include "DynamicField.H"
-
-using namespace Foam;
-
-
-template<class Type>
-void printInfo(const Xfer<Type>& xf)
-{
-    Info<<"    address:" << long(xf.get()) << nl
-        <<"    isNull  = " << isNull(xf) << nl
-        <<"    notNull = " << notNull(xf) << nl
-        <<"    valid() = " << xf.valid() << nl;
-}
-
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-//  Main program:
-
-int main(int argc, char *argv[])
-{
-    labelList lstA(10);
-    labelList lstC
-    {
-        1, 2, 3, 4
-    };
-
-    forAll(lstA, i)
-    {
-        lstA[i] = 5 - i;
-    }
-
-    // Information about null-object
-
-    Info<<"nullObject:" << nl;
-    printInfo(Xfer<labelList>::null());
-    {
-        // This probably needs more work...
-        Xfer<labelList> xf = Xfer<labelList>::null();
-
-        Info<<"copy of nullObject:" << nl;
-        printInfo(xf);
-    }
-
-    Info<< "lstA: " << lstA << nl
-        << "lstC: " << lstC << nl;
-
-    Xfer<labelList> xA = xferMove(lstA);
-    Xfer<labelList> xB;
-
-    labelList lstB( xA );
-
-    Info<< "xA: " << xA() << nl
-        << "xB: " << xB() << nl
-        << "lstA: " << lstA << nl
-        << "lstB: " << lstB << nl
-        << "lstC: " << lstC << nl;
-
-    // Now illegal: xA = lstB;
-
-    xA->transfer(lstB);
-
-    Info<< "xA: " << xA() << nl
-        << "xB: " << xB() << nl
-        << "lstA: " << lstA << nl
-        << "lstB: " << lstB << nl
-        << "lstC: " << lstC << nl;
-
-    xB = xA;
-
-    // Construct with forwarding. For this example, truly ugly.
-    Xfer<labelList> xFwdA =
-        Xfer<labelList>::New
-        (
-            std::initializer_list<label>
-            {
-               1, 2, 10, 20, 15, 24, 200
-            }
-        );
-
-    Xfer<labelList> xFwdB = Xfer<labelList>::New(label(8), 123);
-    Xfer<labelList> xFwdC = Xfer<labelList>::New();
-
-    Info<< nl
-        << "Constructed with forwarding: " << nl
-        << *xFwdA << nl
-        << *xFwdB << nl
-        << *xFwdC << nl
-        << nl;
-
-
-    labelList lstD(xferCopy(lstC));
-    labelList lstE(xferMove(lstC));
-
-    // this must be empty
-    labelList lstF = xferCopy(lstC);
-
-    Info<< "xA: " << xA() << nl
-        << "xB: " << xB() << nl
-        << "lstA: " << lstA << nl
-        << "lstB: " << lstB << nl
-        << "lstC: " << lstC << nl
-        << "lstD: " << lstD << nl
-        << "lstE: " << lstE << nl
-        << "lstF: " << lstF << nl;
-
-    Info<< "xB[" << xB->size() << "]\n";
-
-    // clear the underlying List
-    xB->clear();
-
-    Info<< "xB[" << xB->size() << "]\n";
-
-    DynamicList<label> dl;
-    for (label i = 0; i < 5; ++i)
-    {
-        dl.append(i);
-    }
-
-    face f1(dl);
-    face f2(xferCopy<labelList>(dl));
-
-    Info<< "dl[" << dl.size() << "/" << dl.capacity() << "] " << dl << nl;
-    Info<< "f1: " << f1 << nl;
-    Info<< "f2: " << f2 << nl;
-
-    // add some more labels
-    for (label i = 5; i < 8; ++i)
-    {
-        dl.append(i);
-    }
-
-    // note: xfer() method returns a plain labelList
-    face f3(dl.xfer());
-    Info<< "dl[" << dl.size() << "/" << dl.capacity() << "] " << dl << nl;
-    Info<< "f3: " << f3 << nl;
-
-    Info<<"\nflip faces:" << nl;
-    f1.flip();
-    f3.flip();
-    Info<< "f1: " << f1 << nl;
-    Info<< "f3: " << f3 << nl;
-
-
-    {
-        Info<<"\nTest xfer with fields:" << nl;
-        List<point> list1
-        {
-            { 0, 1, 2 },
-            { 3, 4, 5 },
-            { 6, 7, 8 },
-            { 9, 10, 11 },
-        };
-
-        // Field from Xfer<List>
-        pointField field1(list1.xfer());
-        Info<<nl
-            << "xfer construct from List" << nl
-            <<"input (list) = " << list1 << nl
-            <<"output (field) = " << field1 << nl;
-
-
-        // Field from Xfer<List> ... again
-        pointField field2(field1.xfer());
-        Info<<nl
-            <<"xfer construct from Field (as List): " << nl
-            <<"input (field) = " << field1 << nl
-            <<"output (field) = " << field2 << nl;
-
-
-        // Field from Xfer<Field>
-        pointField field3(xferMove(field2));
-        Info<<nl
-            <<"xfer construct from Field (as Field): " << nl
-            <<"input (field) = " << field2 << nl
-            <<"output (field) = " << field3 << nl;
-
-
-        // Field from Xfer<Field> .. again
-        pointField field4(xferCopy(field3));
-        Info<<nl
-            <<"xfer copy construct from Field (as Field): " << nl
-            <<"input (field) = " << field3 << nl
-            <<"output (field) = " << field4 << nl;
-
-
-        DynamicField<point> dyfield1(xferCopy(field4));
-        Info<<nl
-            <<"xfer copy construct from Field (as Field): " << nl
-            <<"input (field) = " << field4 << nl
-            <<"output (dyn-field) = " << dyfield1 << nl;
-    }
-
-    return 0;
-}
-
-
-// ************************************************************************* //
diff --git a/src/OpenFOAM/memory/Xfer/Xfer.H b/src/OpenFOAM/memory/Xfer/Xfer.H
index 07371b19abc..b9519ccf6dd 100644
--- a/src/OpenFOAM/memory/Xfer/Xfer.H
+++ b/src/OpenFOAM/memory/Xfer/Xfer.H
@@ -30,35 +30,24 @@ Description
     The wrapped object of type \<T\> must implement a transfer() method and
     an operator=() copy method.
 
-    Since it is decided upon construction of the Xfer object whether the
-    parameter is to be copied or transferred, the contents of the resulting
-    Xfer object can be transferred unconditionally. This greatly simplifies
-    defining constructors or methods in other classes with mixed
-    transfer/copy semantics without requiring 2^N different versions.
+\deprecated This class is an artifact from pre-C++11 code (MAR-2018).
 
-    When transferring between dissimilar types, the xferCopyTo() and
-    xferMoveTo() functions can prove useful. An example is transferring
-    from a DynamicList to a List.
-
-    \code
-        List<label> list1;
-        DynamicList<label> list2;
-        ...
-
-        SomeClass obj(xferCopy(list1), xferMoveTo<labelList>(list1));
-    \endcode
+Note
+    This class is an artifact from pre-C++11 code, where it was used
+    as a workaround for the lack of movable references (rvalue).
+    The interfaces previously using Xfer to reclaim memory now use
+    movable references directly or, in the rare case, an autoPtr.
 
 See also
     xferCopy, xferCopyTo, xferMove, xferMoveTo
 
-SourceFiles
-    XferI.H
-
 \*---------------------------------------------------------------------------*/
 
 #ifndef Xfer_H
 #define Xfer_H
 
+#include "nullObject.H"
+
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
 namespace Foam
@@ -87,57 +76,81 @@ public:
 
     // Constructors
 
+        //- Construct with no managed object.
+        inline constexpr Xfer() noexcept : ptr_(nullptr)
+        {}
+
         //- Store object pointer and manage its deletion
         //  Can also be used later to transfer by assignment
-        inline explicit Xfer(T* p = nullptr);
+        inline explicit Xfer(T* p) noexcept : ptr_(p)
+        {}
 
-        //- Construct, transferring its contents
-        inline Xfer(const Xfer<T>& xf);
+        //- Move construct, transferring ownership
+        inline Xfer(const Xfer<T>& xf) noexcept : ptr_(xf.ptr_)
+        {
+            xf.ptr_ = nullptr;
+        }
 
 
     //- Destructor
-    inline ~Xfer();
+    inline ~Xfer() noexcept
+    {
+        delete ptr_;
+        ptr_ = nullptr;
+    }
 
 
     // Static Member Functions
 
         //- Return a null object reference
-        inline static const Xfer<T>& null();
-
-        //- Construct new Xfer container with forwarding arguments to T
-        template<class... Args>
-        inline static Xfer<T> New(Args&&... args);
+        inline static const Xfer<T>& null()
+        {
+            return NullObjectRef<Xfer<T>>();
+        }
 
 
     // Member Functions
 
-        //- Test for valid pointer and not a nullObject reference.
-        inline bool valid() const;
+        //- Test for valid pointer
+        inline bool valid() const noexcept { return ptr_; }
 
         //- Pointer to the underlying object.
-        inline T* get() const;
+        inline T* get() const noexcept { return ptr_; }
 
         //- Rvalue reference to the underlying object.
-        inline T&& rvalue() const;
+        inline T&& rvalue() const { return std::move(*ptr_); }
 
         //- Swaps the managed objects
-        inline void swap(Xfer<T>& other) noexcept;
+        inline void swap(Xfer<T>& other) noexcept
+        {
+            T* p = ptr_;
+            ptr_ = other.ptr_;
+            other.ptr_ = p;
+        }
 
 
     // Member Operators
 
-        //- Transfer contents into the object
-        inline void operator=(const Xfer<T>& xf);
-
         //- Reference to the underlying object
-        inline T& operator*() const;
+        inline T& operator*() const { return *ptr_; }
 
         //- Pointer to the underlying object
-        inline T* operator->() const;
+        inline T* operator->() const { return ptr_; }
 
         //- Reference to the underlying object
-        inline T& operator()() const;
-
+        inline T& operator()() const { return *ptr_; }
+
+        //- Move assignment, transferring ownership
+        inline void operator=(const Xfer<T>& rhs) noexcept
+        {
+            if (this != &rhs)
+            {
+                // clear and swap
+                delete ptr_;
+                ptr_ = rhs.ptr_;
+                rhs.ptr_ = nullptr;
+            }
+        }
 };
 
 
@@ -145,26 +158,41 @@ public:
 
 
 //- Copy construct contents of the \a obj
-//
+//  \deprecated - Xfer should not be used in new code
 //  \sa xferCopyTo, xferMove, xferMoveTo and Foam::Xfer
 template<class T>
-inline Xfer<T> xferCopy(const T& obj);
+inline Xfer<T> xferCopy(const T& obj)
+{
+    return Foam::Xfer<T>(new T(obj));
+}
+
 
 //- Transfer construct contents of the \a obj
+//  \deprecated - Xfer should not be used in new code
 //
 //  \sa xferCopy, xferCopyTo, xferMoveTo and Foam::Xfer
 template<class T>
-inline Xfer<T> xferMove(T& obj);
+inline Xfer<T> xferMove(T& obj)
+{
+    T* ptr = new T;
+    ptr->transfer(obj);
+    return Foam::Xfer<T>(ptr);
+}
 
 
 //- Copy construct contents of the \a obj from dissimilar type
+//  \deprecated - Xfer should not be used in new code
 //
 //  \sa xferCopy, xferMove, xferMoveTo and Foam::Xfer
 template<class T, class From>
-inline Xfer<T> xferCopyTo(const From& obj);
+inline Xfer<T> xferCopyTo(const From& obj)
+{
+    return Foam::Xfer<T>(new T(obj));
+}
 
 
 //- Transfer construct contents of the \a obj from dissimilar type
+//  \deprecated - Xfer should not be used in new code
 //
 //  \par Example Use
 //  \code
@@ -175,7 +203,12 @@ inline Xfer<T> xferCopyTo(const From& obj);
 //
 //  \sa xferCopy, xferCopyTo, xferMove and Foam::Xfer
 template<class T, class From>
-inline Xfer<T> xferMoveTo(From& obj);
+inline Xfer<T> xferMoveTo(From& obj)
+{
+    T* ptr = new T;
+    ptr->transfer(obj);
+    return Foam::Xfer<T>(ptr);
+}
 
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@@ -184,10 +217,6 @@ inline Xfer<T> xferMoveTo(From& obj);
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
-#include "XferI.H"
-
-// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
-
 #endif
 
 // ************************************************************************* //
diff --git a/src/OpenFOAM/memory/Xfer/XferI.H b/src/OpenFOAM/memory/Xfer/XferI.H
deleted file mode 100644
index f203ff074dc..00000000000
--- a/src/OpenFOAM/memory/Xfer/XferI.H
+++ /dev/null
@@ -1,186 +0,0 @@
-/*---------------------------------------------------------------------------*\
-  =========                 |
-  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
-   \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  | Copyright (C) 2018 OpenCFD Ltd.
--------------------------------------------------------------------------------
-License
-    This file is part of OpenFOAM.
-
-    OpenFOAM is free software: you can redistribute it and/or modify it
-    under the terms of the GNU General Public License as published by
-    the Free Software Foundation, either version 3 of the License, or
-    (at your option) any later version.
-
-    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
-    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
-    for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
-
-\*---------------------------------------------------------------------------*/
-
-#include "nullObject.H"
-#include <utility>
-
-// * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * //
-
-template<class T>
-inline const Foam::Xfer<T>& Foam::Xfer<T>::null()
-{
-    return NullObjectRef<Xfer<T>>();
-}
-
-
-template<class T>
-template<class... Args>
-inline Foam::Xfer<T> Foam::Xfer<T>::New(Args&&... args)
-{
-    return Xfer<T>(new T(std::forward<Args>(args)...));
-}
-
-
-// * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
-
-template<class T>
-inline Foam::Xfer<T>::Xfer(T* p)
-:
-    ptr_(p ? p : new T)
-{}
-
-
-template<class T>
-inline Foam::Xfer<T>::Xfer(const Xfer<T>& xf)
-:
-    ptr_(new T)
-{
-    T* p = xf.get();
-
-    if (p && Foam::notNull(p))
-    {
-        ptr_->transfer(*p);
-    }
-}
-
-
-// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
-
-template<class T>
-inline bool Foam::Xfer<T>::valid() const
-{
-    return (ptr_ && Foam::notNull(ptr_));
-}
-
-
-template<class T>
-inline T* Foam::Xfer<T>::get() const
-{
-    return ptr_;
-}
-
-
-template<class T>
-inline T&& Foam::Xfer<T>::rvalue() const
-{
-    // Need check for valid() ?
-    return std::move(*ptr_);
-}
-
-
-template<class T>
-inline void Foam::Xfer<T>::swap(Xfer<T>& other) noexcept
-{
-    // Swap pointers
-    T* p = ptr_;
-    ptr_ = other.ptr;
-    other.ptr_ = p;
-}
-
-
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-template<class T>
-inline Foam::Xfer<T>::~Xfer()
-{
-    if (ptr_ && Foam::notNull(ptr_))
-    {
-        delete ptr_;
-    }
-    ptr_ = nullptr;
-}
-
-
-// * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
-
-template<class T>
-inline void Foam::Xfer<T>::operator=(const Xfer<T>& xf)
-{
-    // Silently ignore attempted copy to self
-    if (this != &xf)
-    {
-        ptr_->transfer(*xf);
-    }
-}
-
-
-template<class T>
-inline T& Foam::Xfer<T>::operator*() const
-{
-    return *ptr_;
-}
-
-
-template<class T>
-inline T* Foam::Xfer<T>::operator->() const
-{
-    return ptr_;
-}
-
-
-template<class T>
-inline T& Foam::Xfer<T>::operator()() const
-{
-    return *ptr_;
-}
-
-
-// * * * * * * * * * * * * * * * Global Functions  * * * * * * * * * * * * * //
-
-template<class T>
-inline Foam::Xfer<T> Foam::xferCopy(const T& obj)
-{
-    T* ptr = new T(obj);
-    return Foam::Xfer<T>(ptr);
-}
-
-
-template<class T, class From>
-inline Foam::Xfer<T> Foam::xferCopyTo(const From& obj)
-{
-    T* ptr = new T(obj);
-    return Foam::Xfer<T>(ptr);
-}
-
-
-template<class T>
-inline Foam::Xfer<T> Foam::xferMove(T& obj)
-{
-    T* ptr = new T;
-    ptr->transfer(obj);
-    return Foam::Xfer<T>(ptr);
-}
-
-
-template<class T, class From>
-inline Foam::Xfer<T> Foam::xferMoveTo(From& obj)
-{
-    T* ptr = new T;
-    ptr->transfer(obj);
-    return Foam::Xfer<T>(ptr);
-}
-
-
-// ************************************************************************* //
-- 
GitLab