From 3a5837e86126f897422077089db204c677534a5a Mon Sep 17 00:00:00 2001
From: Enrico Guiraud <enrico.guiraud@cern.ch>
Date: Wed, 22 May 2019 01:01:43 +0200
Subject: [PATCH] Revert "[RVec] Small Vector Optimisation"

This reverts commit 1047b9cdf72e41a86666fc2576052aeb3fb94242.

Reverting RVec's SBO implementation until we have a proper fix
for the crashes seen in ROOT-10079.
---
 math/vecops/inc/ROOT/RAdoptAllocator.hxx      | 103 +--
 math/vecops/inc/ROOT/RVec.hxx                 | 651 +++++++-----------
 tree/dataframe/inc/ROOT/RDF/ActionHelpers.hxx |   2 +-
 3 files changed, 259 insertions(+), 497 deletions(-)

diff --git a/math/vecops/inc/ROOT/RAdoptAllocator.hxx b/math/vecops/inc/ROOT/RAdoptAllocator.hxx
index b5dc214e3ae..fe6e8b5c634 100644
--- a/math/vecops/inc/ROOT/RAdoptAllocator.hxx
+++ b/math/vecops/inc/ROOT/RAdoptAllocator.hxx
@@ -47,24 +47,6 @@ v.emplace_back(0.);
 now the vector *v* owns its memory as a regular vector.
 **/
 
-template<typename T, bool IsCopyConstructible = std::is_copy_constructible<T>::value>
-class RConstructHelper
-{
-   public:
-      template <class... Args>
-      static void Construct(std::allocator<T> &alloc, T *p, Args &&... args)
-      {
-         alloc.construct(p, args...);
-      }
-};
-
-template <typename T>
-class RConstructHelper<T, false> {
-public:
-   template <class... Args>
-   static void Construct(std::allocator<T> &, T *, Args &&... ){}
-};
-
 template <typename T>
 class RAdoptAllocator {
 public:
@@ -88,31 +70,20 @@ public:
 private:
    enum class EAllocType : char { kOwning, kAdopting, kAdoptingNoAllocYet };
    using StdAllocTraits_t = std::allocator_traits<StdAlloc_t>;
-   pointer fInitialAddress{nullptr};
-   EAllocType fAllocType{EAllocType::kOwning};
+   pointer fInitialAddress = nullptr;
+   EAllocType fAllocType = EAllocType::kOwning;
    StdAlloc_t fStdAllocator;
-   std::size_t fBufferSize{0};
 
 public:
    /// This is the constructor which allows the allocator to adopt a certain memory region.
+   RAdoptAllocator(pointer p) : fInitialAddress(p), fAllocType(EAllocType::kAdoptingNoAllocYet){};
    RAdoptAllocator() = default;
-   RAdoptAllocator(pointer p, std::size_t bufSize = 0)
-      : fInitialAddress(p), fAllocType(p ? EAllocType::kAdoptingNoAllocYet : EAllocType::kOwning), fBufferSize(bufSize)
-   {
-   }
    RAdoptAllocator(const RAdoptAllocator &) = default;
    RAdoptAllocator(RAdoptAllocator &&) = default;
    RAdoptAllocator &operator=(const RAdoptAllocator &) = default;
    RAdoptAllocator &operator=(RAdoptAllocator &&) = default;
    RAdoptAllocator(const RAdoptAllocator<bool> &);
 
-   std::size_t GetBufferSize() const { return fBufferSize;}
-   bool IsAdoptingExternalMemory() const {
-      return fBufferSize == 0 &&
-             fInitialAddress != nullptr &&
-             fAllocType != EAllocType::kOwning;
-   }
-
    /// Construct an object at a certain memory address
    /// \tparam U The type of the memory address at which the object needs to be constructed
    /// \tparam Args The arguments' types necessary for the construction of the object
@@ -123,10 +94,9 @@ public:
    void construct(U *p, Args &&... args)
    {
       // We refuse to do anything since we assume the memory is already initialised
-      if (fBufferSize == 0 && EAllocType::kAdopting == fAllocType)
+      if (EAllocType::kAdopting == fAllocType)
          return;
-      RConstructHelper<U>::Construct(fStdAllocator, p, args...);
-      //fStdAllocator.construct(p, args...);
+      fStdAllocator.construct(p, args...);
    }
 
    /// \brief Allocate some memory
@@ -136,13 +106,11 @@ public:
    {
       if (n > std::size_t(-1) / sizeof(T))
          throw std::bad_alloc();
-      if ((EAllocType::kAdoptingNoAllocYet == fAllocType) &&
-          (fBufferSize == 0 || (fBufferSize > 0 && n <= fBufferSize))) {
+      if (EAllocType::kAdoptingNoAllocYet == fAllocType) {
          fAllocType = EAllocType::kAdopting;
          return fInitialAddress;
       }
       fAllocType = EAllocType::kOwning;
-
       return StdAllocTraits_t::allocate(fStdAllocator, n);
    }
 
@@ -170,7 +138,6 @@ public:
    bool operator!=(const RAdoptAllocator<T> &other) { return !(*this == other); }
 
    size_type max_size() const { return fStdAllocator.max_size(); };
-
 };
 
 // The different semantics of std::vector<bool> make  memory adoption through a
@@ -213,9 +180,6 @@ public:
 
    bool *allocate(std::size_t n) { return fStdAllocator.allocate(n); }
 
-   std::size_t GetBufferSize() const { return 0; }
-   bool IsAdoptingExternalMemory() const { return false; }
-
    template <typename U, class... Args>
    void construct(U *p, Args &&... args)
    {
@@ -235,56 +199,11 @@ public:
    bool operator!=(const RAdoptAllocator &) { return false; }
 };
 
-// Helpers to initialise an allocator according to its value type
-// if bool we initialise a stl allocator, if not an adopt allocator
-template <typename ValueType>
-RAdoptAllocator<ValueType> MakeAdoptAllocator(ValueType *buf, std::size_t n)
-{
-   return RAdoptAllocator<ValueType>(buf, n);
-}
-
-inline std::allocator<bool> MakeAdoptAllocator(bool *, std::size_t)
-{
-   return std::allocator<bool>();
-}
-
-template <typename ValueType>
-RAdoptAllocator<ValueType> MakeAdoptAllocator(ValueType *p)
-{
-   return RAdoptAllocator<ValueType>(p);
-}
-
-inline std::allocator<bool> MakeAdoptAllocator(bool *)
-{
-   return std::allocator<bool>();
-}
-
 template <typename T>
-RAdoptAllocator<T>::RAdoptAllocator(const RAdoptAllocator<bool> &o) : fStdAllocator(o.fStdAllocator)
-{
-}
-
-template <typename Alloc_t>
-std::size_t GetBufferSize(const Alloc_t &alloc)
-{
-   return alloc.GetBufferSize();
-}
-
-inline std::size_t GetBufferSize(const std::allocator<bool> &) { return 0;}
-
-template <typename Alloc_t>
-bool IsAdoptingExternalMemory(const Alloc_t &alloc)
-{
-   return alloc.IsAdoptingExternalMemory();
-}
-
-inline bool IsAdoptingExternalMemory(const std::allocator<bool> &)
-{
-   return false;
-}
-
-} // namespace VecOps
-} // namespace Detail
-} // namespace ROOT
+RAdoptAllocator<T>::RAdoptAllocator(const RAdoptAllocator<bool> &o) : fStdAllocator(o.fStdAllocator) {}
+
+} // End NS VecOps
+} // End NS Detail
+} // End NS ROOT
 
 #endif
diff --git a/math/vecops/inc/ROOT/RVec.hxx b/math/vecops/inc/ROOT/RVec.hxx
index 50e6156a8dd..14133e02ffc 100644
--- a/math/vecops/inc/ROOT/RVec.hxx
+++ b/math/vecops/inc/ROOT/RVec.hxx
@@ -16,9 +16,9 @@
 #define ROOT_RVEC
 
 #ifdef _WIN32
-#define _VECOPS_USE_EXTERN_TEMPLATES false
+   #define _VECOPS_USE_EXTERN_TEMPLATES false
 #else
-#define _VECOPS_USE_EXTERN_TEMPLATES true
+   #define _VECOPS_USE_EXTERN_TEMPLATES true
 #endif
 
 #include <ROOT/RAdoptAllocator.hxx>
@@ -49,7 +49,7 @@
 
 namespace ROOT {
 namespace VecOps {
-template <typename T>
+template<typename T>
 class RVec;
 }
 
@@ -117,8 +117,8 @@ void EmplaceBack(std::vector<bool> &v, Args &&... args)
    v.push_back(std::forward<Args>(args)...);
 }
 
-} // namespace VecOps
-} // namespace Internal
+} // End of VecOps NS
+} // End of Internal NS
 
 namespace VecOps {
 // clang-format off
@@ -268,37 +268,15 @@ hpt->Draw();
 <a name="RVecdoxyref"></a>
 **/
 // clang-format on
-
-template <typename RVec_t, std::size_t BufferSize = RVec_t::fgBufferSize>
-class RStorageVectorFactory {
-public:
-   static typename RVec_t::Impl_t Get(typename RVec_t::pointer buf)
-   {
-      typename RVec_t::Impl_t v(BufferSize, typename RVec_t::value_type(),
-                                ::ROOT::Detail::VecOps::MakeAdoptAllocator(buf, BufferSize));
-      v.resize(0);
-      return v;
-}
-};
-
-template <typename RVec_t>
-class RStorageVectorFactory<RVec_t, 0> {
-public:
-   static typename RVec_t::Impl_t Get(typename RVec_t::value_type *) { return typename RVec_t::Impl_t(); }
-};
-
 template <typename T>
 class RVec {
    // Here we check if T is a bool. This is done in order to decide what type
    // to use as a storage. If T is anything but bool, we use a vector<T, RAdoptAllocator<T>>.
    // If T is a bool, we opt for a plain vector<bool> otherwise we'll not be able
    // to write the data type given the shortcomings of TCollectionProxy design.
-   static constexpr const auto fgIsVecBool = std::is_same<bool, T>::value;
-   using Alloc_t =
-      typename std::conditional<fgIsVecBool, std::allocator<T>, ::ROOT::Detail::VecOps::RAdoptAllocator<T>>::type;
-
+   static constexpr const auto IsVecBool = std::is_same<bool, T>::value;
 public:
-   using Impl_t = std::vector<T, Alloc_t>;
+   using Impl_t = typename std::conditional<IsVecBool, std::vector<bool>, std::vector<T, ::ROOT::Detail::VecOps::RAdoptAllocator<T>>>::type;
    using value_type = typename Impl_t::value_type;
    using size_type = typename Impl_t::size_type;
    using difference_type = typename Impl_t::difference_type;
@@ -308,139 +286,53 @@ public:
    using const_pointer = typename Impl_t::const_pointer;
    // The data_t and const_data_t types are chosen to be void in case T is a bool.
    // This way we can as elegantly as in the STL return void upon calling the data() method.
-   using data_t = typename std::conditional<fgIsVecBool, void, typename Impl_t::pointer>::type;
-   using const_data_t = typename std::conditional<fgIsVecBool, void, typename Impl_t::const_pointer>::type;
+   using data_t = typename std::conditional<IsVecBool, void, typename Impl_t::pointer>::type;
+   using const_data_t = typename std::conditional<IsVecBool, void, typename Impl_t::const_pointer>::type;
    using iterator = typename Impl_t::iterator;
    using const_iterator = typename Impl_t::const_iterator;
    using reverse_iterator = typename Impl_t::reverse_iterator;
    using const_reverse_iterator = typename Impl_t::const_reverse_iterator;
-   static constexpr std::size_t fgBufferSize = std::is_arithmetic<T>::value && !fgIsVecBool ? 8 : 0;
 
 private:
-   using Buffer_t = std::array<T, fgBufferSize>;
-   Buffer_t fBuffer;
-   Alloc_t fAlloc = ::ROOT::Detail::VecOps::MakeAdoptAllocator(fgBufferSize ? fBuffer.data() : nullptr, fgBufferSize);
-   Impl_t fData{fAlloc};
-   bool CanUseBuffer(std::size_t s)
-   {
-      const auto thisBufSize = ::ROOT::Detail::VecOps::GetBufferSize(fAlloc);
-      return thisBufSize && s <= thisBufSize;
-   }
-   bool CanUseBuffer(const RVec &v)
-   {
-      const auto thisBufSize = ::ROOT::Detail::VecOps::GetBufferSize(fAlloc);
-      const auto otherBufSize = ::ROOT::Detail::VecOps::GetBufferSize(v.fAlloc);
-      if (thisBufSize == 0 && otherBufSize == 0)
-         return false;
-      return thisBufSize && v.size() <= thisBufSize;
-   }
-   bool HasBuffer()
-   {
-      // We use the constexpr quantity first for performance reasons. In case it is
-      // 0, the last part of the statement will not even be compiled.
-      return fgBufferSize && 0 != ::ROOT::Detail::VecOps::GetBufferSize(fAlloc);
-   }
-   bool IsAdoptingExternalMemory() { return ::ROOT::Detail::VecOps::IsAdoptingExternalMemory(fAlloc); }
+   Impl_t fData;
 
 public:
    // constructors
+   RVec() {}
 
-   RVec() : fData(RStorageVectorFactory<RVec>::Get(fBuffer.data())) {}
-
-   RVec(pointer p, size_type n) : fAlloc(ROOT::Detail::VecOps::MakeAdoptAllocator(p)), fData(n, T(), fAlloc) {}
+   explicit RVec(size_type count) : fData(count) {}
 
-   explicit RVec(size_type count) : fData(count <= fgBufferSize ? fgBufferSize : 0, T(), fAlloc)
-   {
-      resize(count);
-   }
+   RVec(size_type count, const T &value) : fData(count, value) {}
 
-   RVec(size_type count, const T &value) : fData(count <= fgBufferSize ? fgBufferSize : 0, value, fAlloc)
-   {
-      if (CanUseBuffer(count)) {
-         resize(count);
-      } else {
-         resize(count, value);
-      }
-   }
+   RVec(const RVec<T> &v) : fData(v.fData) {}
 
-   RVec(const RVec &v) : fData(v.size() <= fgBufferSize ? fgBufferSize : 0, T(), fAlloc)
-   {
-      if (CanUseBuffer(v.size()))
-      {
-         resize(v.size());
-         std::copy(v.begin(), v.end(), begin());
-      } else {
-         resize(v.size());
-         std::copy(v.begin(), v.end(), begin());
-      }
-   }
+   RVec(RVec<T> &&v) : fData(std::move(v.fData)) {}
 
-   RVec(const std::vector<T> &v) : fData(v.size(), T(), fAlloc)
-   {
-      if (CanUseBuffer(v.size())) {
-         std::copy(v.begin(), v.end(), fBuffer.begin());
-      } else {
-         std::copy(v.begin(), v.end(), fData.begin());
-      }
-   }
+   RVec(const std::vector<T> &v) : fData(v.cbegin(), v.cend()) {}
 
-   RVec(RVec<T> &&v) : fData(v.size(), T(), fAlloc)
-   {
-      if (v.IsAdoptingExternalMemory())
-      {
-         fAlloc = std::move(v.fAlloc);
-         fData = std::move(v.fData);
-      } else if (CanUseBuffer(v)) {
-         std::copy(v.begin(), v.end(), fBuffer.begin());
-      } else {
-         fData = std::move(v.fData);
-      }
-   }
+   RVec(pointer p, size_type n) : fData(n, T(), ROOT::Detail::VecOps::RAdoptAllocator<T>(p)) {}
 
    template <class InputIt>
-   RVec(InputIt first, InputIt last) : fData(first, last, fAlloc)
-   {
-   }
+   RVec(InputIt first, InputIt last) : fData(first, last) {}
 
-   RVec(std::initializer_list<T> ilist) : fData(ilist.size(), T(), fAlloc)
-   {
-      std::copy(ilist.begin(), ilist.end(), fData.begin());
-   }
+   RVec(std::initializer_list<T> init) : fData(init) {}
 
    // assignment
    RVec<T> &operator=(const RVec<T> &v)
    {
-      if (CanUseBuffer(v.size())) {
-         resize(v.size());
-         std::copy(v.begin(), v.end(), fBuffer.begin());
-      } else {
-         fData = v.fData;
-      }
+      fData = v.fData;
       return *this;
    }
 
    RVec<T> &operator=(RVec<T> &&v)
    {
-      if (v.IsAdoptingExternalMemory()) {
-         fAlloc = std::move(v.fAlloc);
-         fData = std::move(v.fData);
-      } else if (CanUseBuffer(v)) {
-         resize(v.size());
-         std::copy(v.begin(), v.end(), fBuffer.begin());
-      } else {
-         fData = std::move(v.fData);
-      }
+      std::swap(fData, v.fData);
       return *this;
    }
 
    RVec<T> &operator=(std::initializer_list<T> ilist)
    {
-      if (CanUseBuffer(ilist.size())) {
-         resize(ilist.size());
-      } else {
-         fData = Impl_t(ilist.size(), T(), fAlloc);
-      }
-      std::copy(ilist.begin(), ilist.end(), fData.begin());
+      fData = ilist;
       return *this;
    }
 
@@ -513,7 +405,7 @@ public:
    iterator erase(iterator pos) { return fData.erase(pos); }
    iterator erase(iterator first, iterator last) { return fData.erase(first, last); }
    void push_back(T &&value) { fData.push_back(std::forward<T>(value)); }
-   void push_back(const value_type &value) { fData.push_back(value); };
+   void push_back(const value_type& value) { fData.push_back(value); };
    template <class... Args>
    reference emplace_back(Args &&... args)
    {
@@ -522,7 +414,7 @@ public:
    }
    /// This method is intended only for arithmetic types unlike the std::vector
    /// corresponding one which is generic.
-   template <typename U = T, typename std::enable_if<std::is_arithmetic<U>::value, int> * = nullptr>
+   template<typename U = T, typename std::enable_if<std::is_arithmetic<U>::value, int>* = nullptr>
    iterator emplace(const_iterator pos, U value)
    {
       return fData.emplace(pos, value);
@@ -530,59 +422,21 @@ public:
    void pop_back() { fData.pop_back(); }
    void resize(size_type count) { fData.resize(count); }
    void resize(size_type count, const value_type &value) { fData.resize(count, value); }
-   /*
-   void swap(RVec<T> &other)
-   {
-      const auto hasBuf = HasBuffer();
-      const auto otherHasBuf = other.HasBuffer();
-
-      // Case 1: Neither is using a buffer. They could be adopting an
-      // external buffer or own their memory
-      if (!hasBuf && !otherHasBuf) {
-         std::swap(fData, other.fData);
-      // Case 2: This RVec has a buffer and the other one does not.
-      // There are two possibilities here: either the content of the one
-      // which is not using the SMO fits in the one using it or not.
-      } else if (hasBuf && !otherHasBuf) {
-         resize(other.size());
-         if (other.size() <= fgBufferSize) {
-            auto tmpBuf(fBuffer);
-            resize(other.size());
-            std::copy(other.begin(), other.end(), fBuffer.begin());
-            other.resize(tmpBuf.size());
-            std::copy(tmpBuf.begin(), tmpBuf.end(), other.begin());
-         } else {
-            // both have data on the heap.
-            std::swap(fData, other.fData);
-         }
-      // Case 3: This is case 2 but with the operands inverted.
-      } else if (!hasBuf && otherHasBuf) {
-         other.swap(*this);
-      // Case 4: both are in SMO mode. We need to resize and swap contents,
-      // in this order, otherwise we will overwrite the content of the buffer
-      // in case we expand.
-      } else if (hasBuf && otherHasBuf) {
-         const auto thisSize = size();
-         resize(other.size());
-         other.resize(thisSize);
-         std::swap(fBuffer, other.fBuffer);
-      }
-   }
-   */
+   void swap(RVec<T> &other) { std::swap(fData, other.fData); }
 };
 
 ///@name RVec Unary Arithmetic Operators
 ///@{
 
-#define RVEC_UNARY_OPERATOR(OP)          \
-   template <typename T>                 \
-   RVec<T> operator OP(const RVec<T> &v) \
-   {                                     \
-      RVec<T> ret(v);                    \
-      for (auto &x : ret)                \
-         x = OP x;                       \
-      return ret;                        \
-   }
+#define RVEC_UNARY_OPERATOR(OP)                                                \
+template <typename T>                                                          \
+RVec<T> operator OP(const RVec<T> &v)                                          \
+{                                                                              \
+   RVec<T> ret(v);                                                             \
+   for (auto &x : ret)                                                         \
+      x = OP x;                                                                \
+return ret;                                                                    \
+}                                                                              \
 
 RVEC_UNARY_OPERATOR(+)
 RVEC_UNARY_OPERATOR(-)
@@ -594,45 +448,49 @@ RVEC_UNARY_OPERATOR(!)
 ///@name RVec Binary Arithmetic Operators
 ///@{
 
-#define ERROR_MESSAGE(OP) "Cannot call operator " #OP " on vectors of different sizes."
-
-#define RVEC_BINARY_OPERATOR(OP)                                                            \
-   template <typename T0, typename T1>                                                      \
-   auto operator OP(const RVec<T0> &v, const T1 &y)->RVec<decltype(v[0] OP y)>              \
-   {                                                                                        \
-      RVec<decltype(v[0] OP y)> ret(v.size());                                              \
-      auto op = [&y](const T0 &x) { return x OP y; };                                       \
-      std::transform(v.begin(), v.end(), ret.begin(), op);                                  \
-      return ret;                                                                           \
-   }                                                                                        \
-                                                                                            \
-   template <typename T0, typename T1>                                                      \
-   auto operator OP(const T0 &x, const RVec<T1> &v)->RVec<decltype(x OP v[0])>              \
-   {                                                                                        \
-      RVec<decltype(x OP v[0])> ret(v.size());                                              \
-      auto op = [&x](const T1 &y) { return x OP y; };                                       \
-      std::transform(v.begin(), v.end(), ret.begin(), op);                                  \
-      return ret;                                                                           \
-   }                                                                                        \
-                                                                                            \
-   template <typename T0, typename T1>                                                      \
-   auto operator OP(const RVec<T0> &v0, const RVec<T1> &v1)->RVec<decltype(v0[0] OP v1[0])> \
-   {                                                                                        \
-      if (v0.size() != v1.size())                                                           \
-         throw std::runtime_error(ERROR_MESSAGE(OP));                                       \
-                                                                                            \
-      RVec<decltype(v0[0] OP v1[0])> ret(v0.size());                                        \
-      auto op = [](const T0 &x, const T1 &y) { return x OP y; };                            \
-      std::transform(v0.begin(), v0.end(), v1.begin(), ret.begin(), op);                    \
-      return ret;                                                                           \
-   }
+#define ERROR_MESSAGE(OP) \
+ "Cannot call operator " #OP " on vectors of different sizes."
+
+#define RVEC_BINARY_OPERATOR(OP)                                               \
+template <typename T0, typename T1>                                            \
+auto operator OP(const RVec<T0> &v, const T1 &y)                               \
+  -> RVec<decltype(v[0] OP y)>                                                 \
+{                                                                              \
+   RVec<decltype(v[0] OP y)> ret(v.size());                                    \
+   auto op = [&y](const T0 &x) { return x OP y; };                             \
+   std::transform(v.begin(), v.end(), ret.begin(), op);                        \
+   return ret;                                                                 \
+}                                                                              \
+                                                                               \
+template <typename T0, typename T1>                                            \
+auto operator OP(const T0 &x, const RVec<T1> &v)                               \
+  -> RVec<decltype(x OP v[0])>                                                 \
+{                                                                              \
+   RVec<decltype(x OP v[0])> ret(v.size());                                    \
+   auto op = [&x](const T1 &y) { return x OP y; };                             \
+   std::transform(v.begin(), v.end(), ret.begin(), op);                        \
+   return ret;                                                                 \
+}                                                                              \
+                                                                               \
+template <typename T0, typename T1>                                            \
+auto operator OP(const RVec<T0> &v0, const RVec<T1> &v1)                       \
+  -> RVec<decltype(v0[0] OP v1[0])>                                            \
+{                                                                              \
+   if (v0.size() != v1.size())                                                 \
+      throw std::runtime_error(ERROR_MESSAGE(OP));                             \
+                                                                               \
+   RVec<decltype(v0[0] OP v1[0])> ret(v0.size());                              \
+   auto op = [](const T0 &x, const T1 &y) { return x OP y; };                  \
+   std::transform(v0.begin(), v0.end(), v1.begin(), ret.begin(), op);          \
+   return ret;                                                                 \
+}                                                                              \
 
 RVEC_BINARY_OPERATOR(+)
 RVEC_BINARY_OPERATOR(-)
 RVEC_BINARY_OPERATOR(*)
 RVEC_BINARY_OPERATOR(/)
 RVEC_BINARY_OPERATOR(%)
-RVEC_BINARY_OPERATOR (^)
+RVEC_BINARY_OPERATOR(^)
 RVEC_BINARY_OPERATOR(|)
 RVEC_BINARY_OPERATOR(&)
 #undef RVEC_BINARY_OPERATOR
@@ -641,25 +499,25 @@ RVEC_BINARY_OPERATOR(&)
 ///@name RVec Assignment Arithmetic Operators
 ///@{
 
-#define RVEC_ASSIGNMENT_OPERATOR(OP)                                    \
-   template <typename T0, typename T1>                                  \
-   RVec<T0> &operator OP(RVec<T0> &v, const T1 &y)                      \
-   {                                                                    \
-      auto op = [&y](T0 &x) { return x OP y; };                         \
-      std::transform(v.begin(), v.end(), v.begin(), op);                \
-      return v;                                                         \
-   }                                                                    \
-                                                                        \
-   template <typename T0, typename T1>                                  \
-   RVec<T0> &operator OP(RVec<T0> &v0, const RVec<T1> &v1)              \
-   {                                                                    \
-      if (v0.size() != v1.size())                                       \
-         throw std::runtime_error(ERROR_MESSAGE(OP));                   \
-                                                                        \
-      auto op = [](T0 &x, const T1 &y) { return x OP y; };              \
-      std::transform(v0.begin(), v0.end(), v1.begin(), v0.begin(), op); \
-      return v0;                                                        \
-   }
+#define RVEC_ASSIGNMENT_OPERATOR(OP)                                           \
+template <typename T0, typename T1>                                            \
+RVec<T0>& operator OP(RVec<T0> &v, const T1 &y)                                \
+{                                                                              \
+   auto op = [&y](T0 &x) { return x OP y; };                                   \
+   std::transform(v.begin(), v.end(), v.begin(), op);                          \
+   return v;                                                                   \
+}                                                                              \
+                                                                               \
+template <typename T0, typename T1>                                            \
+RVec<T0>& operator OP(RVec<T0> &v0, const RVec<T1> &v1)                        \
+{                                                                              \
+   if (v0.size() != v1.size())                                                 \
+      throw std::runtime_error(ERROR_MESSAGE(OP));                             \
+                                                                               \
+   auto op = [](T0 &x, const T1 &y) { return x OP y; };                        \
+   std::transform(v0.begin(), v0.end(), v1.begin(), v0.begin(), op);           \
+   return v0;                                                                  \
+}                                                                              \
 
 RVEC_ASSIGNMENT_OPERATOR(+=)
 RVEC_ASSIGNMENT_OPERATOR(-=)
@@ -677,36 +535,39 @@ RVEC_ASSIGNMENT_OPERATOR(<<=)
 ///@name RVec Comparison and Logical Operators
 ///@{
 
-#define RVEC_LOGICAL_OPERATOR(OP)                                                                    \
-   template <typename T0, typename T1>                                                               \
-   auto operator OP(const RVec<T0> &v, const T1 &y)->RVec<int> /* avoid std::vector<bool> */         \
-   {                                                                                                 \
-      RVec<int> ret(v.size());                                                                       \
-      auto op = [y](const T0 &x) -> int { return x OP y; };                                          \
-      std::transform(v.begin(), v.end(), ret.begin(), op);                                           \
-      return ret;                                                                                    \
-   }                                                                                                 \
-                                                                                                     \
-   template <typename T0, typename T1>                                                               \
-   auto operator OP(const T0 &x, const RVec<T1> &v)->RVec<int> /* avoid std::vector<bool> */         \
-   {                                                                                                 \
-      RVec<int> ret(v.size());                                                                       \
-      auto op = [x](const T1 &y) -> int { return x OP y; };                                          \
-      std::transform(v.begin(), v.end(), ret.begin(), op);                                           \
-      return ret;                                                                                    \
-   }                                                                                                 \
-                                                                                                     \
-   template <typename T0, typename T1>                                                               \
-   auto operator OP(const RVec<T0> &v0, const RVec<T1> &v1)->RVec<int> /* avoid std::vector<bool> */ \
-   {                                                                                                 \
-      if (v0.size() != v1.size())                                                                    \
-         throw std::runtime_error(ERROR_MESSAGE(OP));                                                \
-                                                                                                     \
-      RVec<int> ret(v0.size());                                                                      \
-      auto op = [](const T0 &x, const T1 &y) -> int { return x OP y; };                              \
-      std::transform(v0.begin(), v0.end(), v1.begin(), ret.begin(), op);                             \
-      return ret;                                                                                    \
-   }
+#define RVEC_LOGICAL_OPERATOR(OP)                                              \
+template <typename T0, typename T1>                                            \
+auto operator OP(const RVec<T0> &v, const T1 &y)                               \
+  -> RVec<int> /* avoid std::vector<bool> */                                   \
+{                                                                              \
+   RVec<int> ret(v.size());                                                    \
+   auto op = [y](const T0 &x) -> int { return x OP y; };                       \
+   std::transform(v.begin(), v.end(), ret.begin(), op);                        \
+   return ret;                                                                 \
+}                                                                              \
+                                                                               \
+template <typename T0, typename T1>                                            \
+auto operator OP(const T0 &x, const RVec<T1> &v)                               \
+  -> RVec<int> /* avoid std::vector<bool> */                                   \
+{                                                                              \
+   RVec<int> ret(v.size());                                                    \
+   auto op = [x](const T1 &y) -> int { return x OP y; };                       \
+   std::transform(v.begin(), v.end(), ret.begin(), op);                        \
+   return ret;                                                                 \
+}                                                                              \
+                                                                               \
+template <typename T0, typename T1>                                            \
+auto operator OP(const RVec<T0> &v0, const RVec<T1> &v1)                       \
+  -> RVec<int> /* avoid std::vector<bool> */                                   \
+{                                                                              \
+   if (v0.size() != v1.size())                                                 \
+      throw std::runtime_error(ERROR_MESSAGE(OP));                             \
+                                                                               \
+   RVec<int> ret(v0.size());                                                   \
+   auto op = [](const T0 &x, const T1 &y) -> int { return x OP y; };           \
+   std::transform(v0.begin(), v0.end(), v1.begin(), ret.begin(), op);          \
+   return ret;                                                                 \
+}                                                                              \
 
 RVEC_LOGICAL_OPERATOR(<)
 RVEC_LOGICAL_OPERATOR(>)
@@ -723,26 +584,13 @@ RVEC_LOGICAL_OPERATOR(||)
 ///@{
 
 /// \cond
-template <typename T>
-struct PromoteTypeImpl;
+template <typename T> struct PromoteTypeImpl;
 
-template <>
-struct PromoteTypeImpl<float> {
-   using Type = float;
-};
-template <>
-struct PromoteTypeImpl<double> {
-   using Type = double;
-};
-template <>
-struct PromoteTypeImpl<long double> {
-   using Type = long double;
-};
+template <> struct PromoteTypeImpl<float>       { using Type = float;       };
+template <> struct PromoteTypeImpl<double>      { using Type = double;      };
+template <> struct PromoteTypeImpl<long double> { using Type = long double; };
 
-template <typename T>
-struct PromoteTypeImpl {
-   using Type = double;
-};
+template <typename T> struct PromoteTypeImpl { using Type = double; };
 
 template <typename T>
 using PromoteType = typename PromoteTypeImpl<T>::Type;
@@ -752,46 +600,46 @@ using PromoteTypes = decltype(PromoteType<U>() + PromoteType<V>());
 
 /// \endcond
 
-#define RVEC_UNARY_FUNCTION(NAME, FUNC)                   \
-   template <typename T>                                  \
-   RVec<PromoteType<T>> NAME(const RVec<T> &v)            \
-   {                                                      \
-      RVec<PromoteType<T>> ret(v.size());                 \
-      auto f = [](const T &x) { return FUNC(x); };        \
-      std::transform(v.begin(), v.end(), ret.begin(), f); \
-      return ret;                                         \
+#define RVEC_UNARY_FUNCTION(NAME, FUNC)                                        \
+   template <typename T>                                                       \
+   RVec<PromoteType<T>> NAME(const RVec<T> &v)                                 \
+   {                                                                           \
+      RVec<PromoteType<T>> ret(v.size());                                      \
+      auto f = [](const T &x) { return FUNC(x); };                             \
+      std::transform(v.begin(), v.end(), ret.begin(), f);                      \
+      return ret;                                                              \
    }
 
-#define RVEC_BINARY_FUNCTION(NAME, FUNC)                                   \
-   template <typename T0, typename T1>                                     \
-   RVec<PromoteTypes<T0, T1>> NAME(const T0 &x, const RVec<T1> &v)         \
-   {                                                                       \
-      RVec<PromoteTypes<T0, T1>> ret(v.size());                            \
-      auto f = [&x](const T1 &y) { return FUNC(x, y); };                   \
-      std::transform(v.begin(), v.end(), ret.begin(), f);                  \
-      return ret;                                                          \
-   }                                                                       \
-                                                                           \
-   template <typename T0, typename T1>                                     \
-   RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &v, const T1 &y)         \
-   {                                                                       \
-      RVec<PromoteTypes<T0, T1>> ret(v.size());                            \
-      auto f = [&y](const T1 &x) { return FUNC(x, y); };                   \
-      std::transform(v.begin(), v.end(), ret.begin(), f);                  \
-      return ret;                                                          \
-   }                                                                       \
-                                                                           \
-   template <typename T0, typename T1>                                     \
-   RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &v0, const RVec<T1> &v1) \
-   {                                                                       \
-      if (v0.size() != v1.size())                                          \
-         throw std::runtime_error(ERROR_MESSAGE(NAME));                    \
-                                                                           \
-      RVec<PromoteTypes<T0, T1>> ret(v0.size());                           \
-      auto f = [](const T0 &x, const T1 &y) { return FUNC(x, y); };        \
-      std::transform(v0.begin(), v0.end(), v1.begin(), ret.begin(), f);    \
-      return ret;                                                          \
-   }
+#define RVEC_BINARY_FUNCTION(NAME, FUNC)                                       \
+   template <typename T0, typename T1>                                         \
+   RVec<PromoteTypes<T0, T1>> NAME(const T0 &x, const RVec<T1> &v)             \
+   {                                                                           \
+      RVec<PromoteTypes<T0, T1>> ret(v.size());                                \
+      auto f = [&x](const T1 &y) { return FUNC(x, y); };                       \
+      std::transform(v.begin(), v.end(), ret.begin(), f);                      \
+      return ret;                                                              \
+   }                                                                           \
+                                                                               \
+   template <typename T0, typename T1>                                         \
+   RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &v, const T1 &y)             \
+   {                                                                           \
+      RVec<PromoteTypes<T0, T1>> ret(v.size());                                \
+      auto f = [&y](const T1 &x) { return FUNC(x, y); };                       \
+      std::transform(v.begin(), v.end(), ret.begin(), f);                      \
+      return ret;                                                              \
+   }                                                                           \
+                                                                               \
+   template <typename T0, typename T1>                                         \
+   RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &v0, const RVec<T1> &v1)     \
+   {                                                                           \
+      if (v0.size() != v1.size())                                              \
+         throw std::runtime_error(ERROR_MESSAGE(NAME));                        \
+                                                                               \
+      RVec<PromoteTypes<T0, T1>> ret(v0.size());                               \
+      auto f = [](const T0 &x, const T1 &y) { return FUNC(x, y); };            \
+      std::transform(v0.begin(), v0.end(), v1.begin(), ret.begin(), f);        \
+      return ret;                                                              \
+   }                                                                           \
 
 #define RVEC_STD_UNARY_FUNCTION(F) RVEC_UNARY_FUNCTION(F, std::F)
 #define RVEC_STD_BINARY_FUNCTION(F) RVEC_BINARY_FUNCTION(F, std::F)
@@ -924,8 +772,7 @@ T Sum(const RVec<T> &v)
 template <typename T>
 double Mean(const RVec<T> &v)
 {
-   if (v.empty())
-      return 0.;
+   if (v.empty()) return 0.;
    return double(Sum(v)) / v.size();
 }
 
@@ -1012,17 +859,13 @@ template <typename T>
 double Var(const RVec<T> &v)
 {
    const std::size_t size = v.size();
-   if (size < std::size_t(2))
-      return 0.;
+   if (size < std::size_t(2)) return 0.;
    T sum_squares(0), squared_sum(0);
-   auto pred = [&sum_squares, &squared_sum](const T &x) {
-      sum_squares += x * x;
-      squared_sum += x;
-   };
+   auto pred = [&sum_squares, &squared_sum](const T& x) {sum_squares+=x*x; squared_sum+=x;};
    std::for_each(v.begin(), v.end(), pred);
    squared_sum *= squared_sum;
-   const auto dsize = (double)size;
-   return 1. / (dsize - 1.) * (sum_squares - squared_sum / dsize);
+   const auto dsize = (double) size;
+   return 1. / (dsize - 1.) * (sum_squares - squared_sum / dsize );
 }
 
 /// Get the standard deviation of the elements of an RVec
@@ -1140,6 +983,12 @@ auto All(const RVec<T> &v) -> decltype(v[0] == false)
    return true;
 }
 
+template <typename T>
+void swap(RVec<T> &lhs, RVec<T> &rhs)
+{
+   lhs.swap(rhs);
+}
+
 /// Return an RVec of indices that sort the input RVec
 ///
 /// Example code, at the ROOT prompt:
@@ -1292,18 +1141,17 @@ RVec<T> Sort(const RVec<T> &v, Compare &&c)
 /// using namespace ROOT::VecOps;
 /// auto comb_idx = Combinations(3, 2);
 /// comb_idx
-/// // (ROOT::VecOps::RVec<ROOT::VecOps::RVec<ROOT::VecOps::RVec<double>::size_type> >) { { 0, 0, 1, 1, 2, 2 }, { 0, 1,
-/// 0, 1, 0, 1 } }
+/// // (ROOT::VecOps::RVec<ROOT::VecOps::RVec<ROOT::VecOps::RVec<double>::size_type> >) { { 0, 0, 1, 1, 2, 2 }, { 0, 1, 0, 1, 0, 1 } }
 /// ~~~
-inline RVec<RVec<std::size_t>> Combinations(const std::size_t s1, const std::size_t s2)
+inline RVec<RVec<std::size_t>> Combinations(const std::size_t size1, const std::size_t size2)
 {
    using size_type = std::size_t;
    RVec<RVec<size_type>> r(2);
-   r[0].resize(s1 * s2);
-   r[1].resize(s1 * s2);
+   r[0].resize(size1*size2);
+   r[1].resize(size1*size2);
    size_type c = 0;
-   for (size_type i = 0; i < s1; i++) {
-      for (size_type j = 0; j < s2; j++) {
+   for(size_type i=0; i<size1; i++) {
+      for(size_type j=0; j<size2; j++) {
          r[0][c] = i;
          r[1][c] = j;
          c++;
@@ -1344,14 +1192,16 @@ RVec<RVec<typename RVec<T1>::size_type>> Combinations(const RVec<T1> &v1, const
 /// (ROOT::VecOps::RVec<ROOT::VecOps::RVec<ROOT::VecOps::RVec<double>::size_type> >) { { 0, 1, 2, 3 } }
 /// auto v_2 = Combinations(v, 2);
 /// auto v_2
-/// (ROOT::VecOps::RVec<ROOT::VecOps::RVec<ROOT::VecOps::RVec<double>::size_type> >) { { 0, 0, 0, 1, 1, 2 }, { 1, 2, 3,
-/// 2, 3, 3 } } auto v_3 = Combinations(v, 3); v_3
-/// (ROOT::VecOps::RVec<ROOT::VecOps::RVec<ROOT::VecOps::RVec<double>::size_type> >) { { 0, 0, 0, 1 }, { 1, 1, 2, 2 }, {
-/// 2, 3, 3, 3 } } auto v_4 = Combinations(v, 4); v_4
+/// (ROOT::VecOps::RVec<ROOT::VecOps::RVec<ROOT::VecOps::RVec<double>::size_type> >) { { 0, 0, 0, 1, 1, 2 }, { 1, 2, 3, 2, 3, 3 } }
+/// auto v_3 = Combinations(v, 3);
+/// v_3
+/// (ROOT::VecOps::RVec<ROOT::VecOps::RVec<ROOT::VecOps::RVec<double>::size_type> >) { { 0, 0, 0, 1 }, { 1, 1, 2, 2 }, { 2, 3, 3, 3 } }
+/// auto v_4 = Combinations(v, 4);
+/// v_4
 /// (ROOT::VecOps::RVec<ROOT::VecOps::RVec<ROOT::VecOps::RVec<double>::size_type> >) { { 0 }, { 1 }, { 2 }, { 3 } }
 /// ~~~
 template <typename T>
-RVec<RVec<typename RVec<T>::size_type>> Combinations(const RVec<T> &v, const typename RVec<T>::size_type n)
+RVec<RVec<typename RVec<T>::size_type>> Combinations(const RVec<T>& v, const typename RVec<T>::size_type n)
 {
    using size_type = typename RVec<T>::size_type;
    const size_type s = v.size();
@@ -1361,16 +1211,16 @@ RVec<RVec<typename RVec<T>::size_type>> Combinations(const RVec<T> &v, const typ
       throw std::runtime_error(ss.str());
    }
    RVec<size_type> indices(s);
-   for (size_type k = 0; k < s; k++)
+   for(size_type k=0; k<s; k++)
       indices[k] = k;
    RVec<RVec<size_type>> c(n);
-   for (size_type k = 0; k < n; k++)
+   for(size_type k=0; k<n; k++)
       c[k].emplace_back(indices[k]);
    while (true) {
       bool run_through = true;
       long i = n - 1;
-      for (; i >= 0; i--) {
-         if (indices[i] != i + s - n) {
+      for (; i>=0; i--) {
+         if (indices[i] != i + s - n){
             run_through = false;
             break;
          }
@@ -1379,9 +1229,9 @@ RVec<RVec<typename RVec<T>::size_type>> Combinations(const RVec<T> &v, const typ
          return c;
       }
       indices[i]++;
-      for (long j = i + 1; j < (long)n; j++)
-         indices[j] = indices[j - 1] + 1;
-      for (size_type k = 0; k < n; k++)
+      for (long j=i+1; j<(long)n; j++)
+         indices[j] = indices[j-1] + 1;
+      for(size_type k=0; k<n; k++)
          c[k].emplace_back(indices[k]);
    }
 }
@@ -1403,8 +1253,8 @@ RVec<typename RVec<T>::size_type> Nonzero(const RVec<T> &v)
    RVec<size_type> r;
    const auto size = v.size();
    r.reserve(size);
-   for (size_type i = 0; i < size; i++) {
-      if (v[i] != 0) {
+   for(size_type i=0; i<size; i++) {
+      if(v[i] != 0) {
          r.emplace_back(i);
       }
    }
@@ -1428,18 +1278,17 @@ RVec<typename RVec<T>::size_type> Nonzero(const RVec<T> &v)
 /// // (ROOT::VecOps::RVec<double>) { 1.0000000, 2.0000000 }
 /// ~~~
 template <typename T>
-RVec<T> Intersect(const RVec<T> &v1, const RVec<T> &v2, bool v2_is_sorted = false)
+RVec<T> Intersect(const RVec<T>& v1, const RVec<T>& v2, bool v2_is_sorted = false)
 {
    RVec<T> v2_sorted;
-   if (!v2_is_sorted)
-      v2_sorted = Sort(v2);
+   if (!v2_is_sorted) v2_sorted = Sort(v2);
    const auto v2_begin = v2_is_sorted ? v2.begin() : v2_sorted.begin();
    const auto v2_end = v2_is_sorted ? v2.end() : v2_sorted.end();
    RVec<T> r;
    const auto size = v1.size();
    r.reserve(size);
    using size_type = typename RVec<T>::size_type;
-   for (size_type i = 0; i < size; i++) {
+   for(size_type i=0; i<size; i++) {
       if (std::binary_search(v2_begin, v2_end, v1[i])) {
          r.emplace_back(v1[i]);
       }
@@ -1463,13 +1312,13 @@ RVec<T> Intersect(const RVec<T> &v1, const RVec<T> &v2, bool v2_is_sorted = fals
 /// // (ROOT::VecOps::RVec<double> &) { -1.0000000, 2.0000000, 3.0000000 }
 /// ~~~
 template <typename T>
-RVec<T> Where(const RVec<int> &c, const RVec<T> &v1, const RVec<T> &v2)
+RVec<T> Where(const RVec<int>& c, const RVec<T>& v1, const RVec<T>& v2)
 {
    using size_type = typename RVec<T>::size_type;
    const size_type size = c.size();
    RVec<T> r;
    r.reserve(size);
-   for (size_type i = 0; i < size; i++) {
+   for (size_type i=0; i<size; i++) {
       r.emplace_back(c[i] != 0 ? v1[i] : v2[i]);
    }
    return r;
@@ -1491,13 +1340,13 @@ RVec<T> Where(const RVec<int> &c, const RVec<T> &v1, const RVec<T> &v2)
 /// // (ROOT::VecOps::RVec<double>) { 4.0000000, 2.0000000, 3.0000000 }
 /// ~~~
 template <typename T>
-RVec<T> Where(const RVec<int> &c, const RVec<T> &v1, T v2)
+RVec<T> Where(const RVec<int>& c, const RVec<T>& v1, T v2)
 {
    using size_type = typename RVec<T>::size_type;
    const size_type size = c.size();
    RVec<T> r;
    r.reserve(size);
-   for (size_type i = 0; i < size; i++) {
+   for (size_type i=0; i<size; i++) {
       r.emplace_back(c[i] != 0 ? v1[i] : v2);
    }
    return r;
@@ -1519,13 +1368,13 @@ RVec<T> Where(const RVec<int> &c, const RVec<T> &v1, T v2)
 /// // (ROOT::VecOps::RVec<double>) { 1.0000000, 4.0000000, 4.0000000 }
 /// ~~~
 template <typename T>
-RVec<T> Where(const RVec<int> &c, T v1, const RVec<T> &v2)
+RVec<T> Where(const RVec<int>& c, T v1, const RVec<T>& v2)
 {
    using size_type = typename RVec<T>::size_type;
    const size_type size = c.size();
    RVec<T> r;
    r.reserve(size);
-   for (size_type i = 0; i < size; i++) {
+   for (size_type i=0; i<size; i++) {
       r.emplace_back(c[i] != 0 ? v1 : v2[i]);
    }
    return r;
@@ -1545,13 +1394,13 @@ RVec<T> Where(const RVec<int> &c, T v1, const RVec<T> &v2)
 /// // (ROOT::VecOps::RVec<double>) { 2.0000000, 4.0000000, 4.0000000 }
 /// ~~~
 template <typename T>
-RVec<T> Where(const RVec<int> &c, T v1, T v2)
+RVec<T> Where(const RVec<int>& c, T v1, T v2)
 {
    using size_type = typename RVec<T>::size_type;
    const size_type size = c.size();
    RVec<T> r;
    r.reserve(size);
-   for (size_type i = 0; i < size; i++) {
+   for (size_type i=0; i<size; i++) {
       r.emplace_back(c[i] != 0 ? v1 : v2);
    }
    return r;
@@ -1805,12 +1654,16 @@ std::ostream &operator<<(std::ostream &os, const RVec<T> &v)
 
 #if (_VECOPS_USE_EXTERN_TEMPLATES)
 
-#define RVEC_EXTERN_UNARY_OPERATOR(T, OP) extern template RVec<T> operator OP<T>(const RVec<T> &);
+#define RVEC_EXTERN_UNARY_OPERATOR(T, OP) \
+   extern template RVec<T> operator OP<T>(const RVec<T> &);
 
-#define RVEC_EXTERN_BINARY_OPERATOR(T, OP)                                                          \
-   extern template auto operator OP<T, T>(const T &x, const RVec<T> &v)->RVec<decltype(x OP v[0])>; \
-   extern template auto operator OP<T, T>(const RVec<T> &v, const T &y)->RVec<decltype(v[0] OP y)>; \
-   extern template auto operator OP<T, T>(const RVec<T> &v0, const RVec<T> &v1)->RVec<decltype(v0[0] OP v1[0])>;
+#define RVEC_EXTERN_BINARY_OPERATOR(T, OP)                                     \
+   extern template auto operator OP<T, T>(const T &x, const RVec<T> &v)        \
+      -> RVec<decltype(x OP v[0])>;                                            \
+   extern template auto operator OP<T, T>(const RVec<T> &v, const T &y)        \
+      -> RVec<decltype(v[0] OP y)>;                                            \
+   extern template auto operator OP<T, T>(const RVec<T> &v0, const RVec<T> &v1)\
+      -> RVec<decltype(v0[0] OP v1[0])>;
 
 #define RVEC_EXTERN_ASSIGN_OPERATOR(T, OP)                           \
    extern template RVec<T> &operator OP<T, T>(RVec<T> &, const T &); \
@@ -1821,26 +1674,26 @@ std::ostream &operator<<(std::ostream &os, const RVec<T> &v)
    extern template RVec<int> operator OP<T, T>(const T &, const RVec<T> &); \
    extern template RVec<int> operator OP<T, T>(const RVec<T> &, const RVec<T> &);
 
-#define RVEC_EXTERN_FLOAT_TEMPLATE(T)  \
-   extern template class RVec<T>;      \
-   RVEC_EXTERN_UNARY_OPERATOR(T, +)    \
-   RVEC_EXTERN_UNARY_OPERATOR(T, -)    \
-   RVEC_EXTERN_UNARY_OPERATOR(T, !)    \
-   RVEC_EXTERN_BINARY_OPERATOR(T, +)   \
-   RVEC_EXTERN_BINARY_OPERATOR(T, -)   \
-   RVEC_EXTERN_BINARY_OPERATOR(T, *)   \
-   RVEC_EXTERN_BINARY_OPERATOR(T, /)   \
-   RVEC_EXTERN_ASSIGN_OPERATOR(T, +=)  \
-   RVEC_EXTERN_ASSIGN_OPERATOR(T, -=)  \
-   RVEC_EXTERN_ASSIGN_OPERATOR(T, *=)  \
-   RVEC_EXTERN_ASSIGN_OPERATOR(T, /=)  \
-   RVEC_EXTERN_LOGICAL_OPERATOR(T, <)  \
-   RVEC_EXTERN_LOGICAL_OPERATOR(T, >)  \
-   RVEC_EXTERN_LOGICAL_OPERATOR(T, ==) \
-   RVEC_EXTERN_LOGICAL_OPERATOR(T, !=) \
-   RVEC_EXTERN_LOGICAL_OPERATOR(T, <=) \
-   RVEC_EXTERN_LOGICAL_OPERATOR(T, >=) \
-   RVEC_EXTERN_LOGICAL_OPERATOR(T, &&) \
+#define RVEC_EXTERN_FLOAT_TEMPLATE(T)   \
+   extern template class RVec<T>;       \
+   RVEC_EXTERN_UNARY_OPERATOR(T, +)     \
+   RVEC_EXTERN_UNARY_OPERATOR(T, -)     \
+   RVEC_EXTERN_UNARY_OPERATOR(T, !)     \
+   RVEC_EXTERN_BINARY_OPERATOR(T, +)    \
+   RVEC_EXTERN_BINARY_OPERATOR(T, -)    \
+   RVEC_EXTERN_BINARY_OPERATOR(T, *)    \
+   RVEC_EXTERN_BINARY_OPERATOR(T, /)    \
+   RVEC_EXTERN_ASSIGN_OPERATOR(T, +=)   \
+   RVEC_EXTERN_ASSIGN_OPERATOR(T, -=)   \
+   RVEC_EXTERN_ASSIGN_OPERATOR(T, *=)   \
+   RVEC_EXTERN_ASSIGN_OPERATOR(T, /=)   \
+   RVEC_EXTERN_LOGICAL_OPERATOR(T, <)   \
+   RVEC_EXTERN_LOGICAL_OPERATOR(T, >)   \
+   RVEC_EXTERN_LOGICAL_OPERATOR(T, ==)  \
+   RVEC_EXTERN_LOGICAL_OPERATOR(T, !=)  \
+   RVEC_EXTERN_LOGICAL_OPERATOR(T, <=)  \
+   RVEC_EXTERN_LOGICAL_OPERATOR(T, >=)  \
+   RVEC_EXTERN_LOGICAL_OPERATOR(T, &&)  \
    RVEC_EXTERN_LOGICAL_OPERATOR(T, ||)
 
 #define RVEC_EXTERN_INTEGER_TEMPLATE(T) \
@@ -1880,13 +1733,13 @@ RVEC_EXTERN_INTEGER_TEMPLATE(char)
 RVEC_EXTERN_INTEGER_TEMPLATE(short)
 RVEC_EXTERN_INTEGER_TEMPLATE(int)
 RVEC_EXTERN_INTEGER_TEMPLATE(long)
-// RVEC_EXTERN_INTEGER_TEMPLATE(long long)
+//RVEC_EXTERN_INTEGER_TEMPLATE(long long)
 
 RVEC_EXTERN_INTEGER_TEMPLATE(unsigned char)
 RVEC_EXTERN_INTEGER_TEMPLATE(unsigned short)
 RVEC_EXTERN_INTEGER_TEMPLATE(unsigned int)
 RVEC_EXTERN_INTEGER_TEMPLATE(unsigned long)
-// RVEC_EXTERN_INTEGER_TEMPLATE(unsigned long long)
+//RVEC_EXTERN_INTEGER_TEMPLATE(unsigned long long)
 
 RVEC_EXTERN_FLOAT_TEMPLATE(float)
 RVEC_EXTERN_FLOAT_TEMPLATE(double)
@@ -1898,11 +1751,12 @@ RVEC_EXTERN_FLOAT_TEMPLATE(double)
 #undef RVEC_EXTERN_INTEGER_TEMPLATE
 #undef RVEC_EXTERN_FLOAT_TEMPLATE
 
-#define RVEC_EXTERN_UNARY_FUNCTION(T, NAME, FUNC) extern template RVec<PromoteType<T>> NAME(const RVec<T> &);
+#define RVEC_EXTERN_UNARY_FUNCTION(T, NAME, FUNC) \
+   extern template RVec<PromoteType<T>> NAME(const RVec<T> &);
 
 #define RVEC_EXTERN_STD_UNARY_FUNCTION(T, F) RVEC_EXTERN_UNARY_FUNCTION(T, F, std::F)
 
-#define RVEC_EXTERN_BINARY_FUNCTION(T0, T1, NAME, FUNC)                           \
+#define RVEC_EXTERN_BINARY_FUNCTION(T0, T1, NAME, FUNC)                            \
    extern template RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &, const T1 &); \
    extern template RVec<PromoteTypes<T0, T1>> NAME(const T0 &, const RVec<T1> &); \
    extern template RVec<PromoteTypes<T0, T1>> NAME(const RVec<T0> &, const RVec<T1> &);
@@ -1945,7 +1799,7 @@ RVEC_EXTERN_FLOAT_TEMPLATE(double)
    RVEC_EXTERN_STD_UNARY_FUNCTION(T, erf)        \
    RVEC_EXTERN_STD_UNARY_FUNCTION(T, erfc)       \
    RVEC_EXTERN_STD_UNARY_FUNCTION(T, lgamma)     \
-   RVEC_EXTERN_STD_UNARY_FUNCTION(T, tgamma)
+   RVEC_EXTERN_STD_UNARY_FUNCTION(T, tgamma)     \
 
 RVEC_EXTERN_STD_FUNCTIONS(float)
 RVEC_EXTERN_STD_FUNCTIONS(double)
@@ -1979,22 +1833,11 @@ RVEC_EXTERN_VDT_UNARY_FUNCTION(double, fast_atan)
 
 #endif // _VECOPS_USE_EXTERN_TEMPLATES
 
-} // namespace VecOps
+} // End of VecOps NS
 
 // Allow to use RVec as ROOT::RVec
 using ROOT::VecOps::RVec;
 
-} // namespace ROOT
-
-namespace std {
-template <typename T>
-void swap(ROOT::VecOps::RVec<T> &lhs, ROOT::VecOps::RVec<T> &rhs)
-{
-   auto tmp(std::move(lhs));
-   lhs = std::move(rhs);
-   rhs = std::move(tmp);
-}
-} // namespace std
-
+} // End of ROOT NS
 
 #endif // ROOT_RVEC
diff --git a/tree/dataframe/inc/ROOT/RDF/ActionHelpers.hxx b/tree/dataframe/inc/ROOT/RDF/ActionHelpers.hxx
index e1ae67a260a..bb4fc3c721b 100644
--- a/tree/dataframe/inc/ROOT/RDF/ActionHelpers.hxx
+++ b/tree/dataframe/inc/ROOT/RDF/ActionHelpers.hxx
@@ -507,7 +507,7 @@ public:
 // 4. The column is an RVec, the collection is a vector
 
 template <typename V, typename COLL>
-void FillColl(V& v, COLL& c) {
+void FillColl(V&& v, COLL& c) {
    c.emplace_back(v);
 }
 
-- 
GitLab