//============================================================================ // Copyright (c) Kitware, Inc. // All rights reserved. // See LICENSE.txt for details. // This software is distributed WITHOUT ANY WARRANTY; without even // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. // // Copyright 2016 Sandia Corporation. // Copyright 2016 UT-Battelle, LLC. // Copyright 2016 Los Alamos National Security. // // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, // the U.S. Government retains certain rights in this software. // // Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National // Laboratory (LANL), the U.S. Government retains certain rights in // this software. //============================================================================ #ifndef vtk_m_internal_ArrayPortalValueReference_h #define vtk_m_internal_ArrayPortalValueReference_h #include #include #include namespace vtkm { namespace internal { /// \brief A value class for returning setable values of an ArrayPortal /// /// \c ArrayPortal classes have a pair of \c Get and \c Set methods that /// retreive and store values in the array. This is to make it easy to /// implement the \c ArrayPortal even it is not really an array. However, there /// are some cases where the code structure expects a reference to a value that /// can be set. For example, the \c IteratorFromArrayPortal class must return /// something from its * operator that behaves like a reference. /// /// For cases of this nature \c ArrayPortalValueReference can be used. This /// class is constructured with an \c ArrayPortal and an index into the array. /// The object then behaves like a reference to the value in the array. If you /// set this reference object to a new value, it will call \c Set on the /// \c ArrayPortal to insert the value into the array. /// template struct ArrayPortalValueReference { using ValueType = typename ArrayPortalType::ValueType; VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT ArrayPortalValueReference(const ArrayPortalType &portal, vtkm::Id index) : Portal(portal), Index(index) { } VTKM_CONT void Swap( ArrayPortalValueReference &rhs ) throw() { //we need use the explicit type not a proxy temp object //A proxy temp object would point to the same underlying data structure //and would not hold the old value of *this once *this was set to rhs. const ValueType aValue = *this; *this = rhs; rhs = aValue; } VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT ArrayPortalValueReference &operator=( const ArrayPortalValueReference &rhs) { this->Portal.Set(this->Index, rhs.Portal.Get(rhs.Index)); return *this; } VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT ValueType operator=(const ValueType& value) { this->Portal.Set(this->Index, value); return value; } VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT operator ValueType(void) const { return this->Portal.Get(this->Index); } const ArrayPortalType& Portal; vtkm::Id Index; }; //implement a custom swap function, since the std::swap won't work //since we return RValues instead of Lvalues template void swap( vtkm::internal::ArrayPortalValueReference a, vtkm::internal::ArrayPortalValueReference b) { a.Swap(b); } } } // namespace vtkm::internal namespace vtkm { // Make specialization for TypeTraits and VecTraits so that the reference // behaves the same as the value. template struct TypeTraits > : vtkm::TypeTraits::ValueType> { }; template struct VecTraits > : vtkm::VecTraits::ValueType> { }; } // namespace vtkm #endif //vtk_m_internal_ArrayPortalValueReference_h