Add default constructors/destructors/assignment to ArrayHandle classes

The ArrayHandle classes all exclusively work in the control environment.
However, CUDA likes to add __device__ to constructors, destructors, and
assignment operators it automatically adds. This in turn causes warnings
about the __device__ function using host-only classes (like
boost::shared_ptr). Solve this problem by adding explicit methods for
all of these.

Implemented this by wrapping up all these default objects in a macro.
This also solved the problem of other constructors that are necessary
for array handles such as a constructor that takes the base array
handle.
This commit is contained in:
Kenneth Moreland 2015-10-21 13:36:27 -06:00
parent e028f2af99
commit 65c2261892
12 changed files with 169 additions and 254 deletions

@ -117,6 +117,93 @@ struct ArrayHandleCheck
} // namespace internal
namespace detail {
template<typename T> struct GetTypeInParentheses;
template<typename T>
struct GetTypeInParentheses<void(T)>
{
typedef T type;
};
} // namespace detail
// Implementation for VTKM_ARRAY_HANDLE_SUBCLASS macros
#define VTK_M_ARRAY_HANDLE_SUBCLASS_IMPL(classname, fullclasstype, superclass, typename__) \
typedef typename__ vtkm::cont::detail::GetTypeInParentheses<void fullclasstype>::type Thisclass;\
typedef typename__ vtkm::cont::detail::GetTypeInParentheses<void superclass>::type Superclass;\
\
VTKM_IS_ARRAY_HANDLE(Superclass); \
\
VTKM_CONT_EXPORT \
classname() : Superclass() { } \
\
VTKM_CONT_EXPORT \
classname(const Thisclass &src) : Superclass(src) { } \
\
VTKM_CONT_EXPORT \
classname(const vtkm::cont::ArrayHandle<typename__ Superclass::ValueType, typename__ Superclass::StorageTag> &src) : Superclass(src) { } \
\
VTKM_CONT_EXPORT \
virtual ~classname() { } \
\
VTKM_CONT_EXPORT \
Thisclass &operator=(const Thisclass &src) \
{ \
this->Superclass::operator=(src); \
return *this; \
} \
\
typedef typename__ Superclass::ValueType ValueType; \
typedef typename__ Superclass::StorageTag StorageTag
/// \brief Macro to make default methods in ArrayHandle subclasses.
///
/// This macro defines the default constructors, destructors and assignment
/// operators for ArrayHandle subclasses that are templates. The ArrayHandle
/// subclasses are assumed to be empty convenience classes. The macro should be
/// defined after a \c public: declaration.
///
/// This macro takes three arguments. The first argument is the classname.
/// The second argument is the full class type. The third argument is the
/// superclass type (either \c ArrayHandle or another sublcass). Because
/// C macros do not handle template parameters very well (the preprocessor
/// thinks the template commas are macro argument commas), the second and
/// third arguments must be wrapped in parentheses.
///
/// This macro also defines a Superclass typedef as well as ValueType and
/// StorageTag.
///
/// Note that this macor only works on ArrayHandle subclasses that are
/// templated. For ArrayHandle sublcasses that are not templates, use
/// VTKM_ARRAY_HANDLE_SUBCLASS_NT.
///
#define VTKM_ARRAY_HANDLE_SUBCLASS(classname, fullclasstype, superclass) \
VTK_M_ARRAY_HANDLE_SUBCLASS_IMPL(classname, fullclasstype, superclass, typename)
/// \brief Macro to make default methods in ArrayHandle subclasses.
///
/// This macro defines the default constructors, destructors and assignment
/// operators for ArrayHandle subclasses that are not templates. The
/// ArrayHandle subclasses are assumed to be empty convenience classes. The
/// macro should be defined after a \c public: declaration.
///
/// This macro takes two arguments. The first argument is the classname. The
/// second argument is the superclass type (either \c ArrayHandle or another
/// sublcass). Because C macros do not handle template parameters very well
/// (the preprocessor thinks the template commas are macro argument commas),
/// the second argument must be wrapped in parentheses.
///
/// This macro also defines a Superclass typedef as well as ValueType and
/// StorageTag.
///
/// Note that this macor only works on ArrayHandle subclasses that are not
/// templated. For ArrayHandle sublcasses that are are templates, use
/// VTKM_ARRAY_HANDLE_SUBCLASS.
///
#define VTKM_ARRAY_HANDLE_SUBCLASS_NT(classname, superclass) \
VTK_M_ARRAY_HANDLE_SUBCLASS_IMPL(classname, (classname), superclass, )
/// \brief Manages an array-worth of data.
///
/// \c ArrayHandle manages as array of data that can be manipulated by VTKm

@ -48,42 +48,26 @@ struct Cast
/// and a type, it creates a new handle that returns the elements of the array cast
/// to the specified type.
///
template <typename ValueType, typename ArrayHandleType>
template <typename T, typename ArrayHandleType>
class ArrayHandleCast :
public vtkm::cont::ArrayHandleTransform<
ValueType,
T,
ArrayHandleType,
internal::Cast<typename ArrayHandleType::ValueType, ValueType> >
internal::Cast<typename ArrayHandleType::ValueType, T> >
{
public:
typedef vtkm::cont::ArrayHandleTransform<
ValueType,
ArrayHandleType,
internal::Cast<typename ArrayHandleType::ValueType, ValueType> > SuperClass;
typedef typename SuperClass::StorageTag StorageTag;
VTKM_CONT_EXPORT
ArrayHandleCast() : SuperClass()
{ }
VTKM_CONT_EXPORT
ArrayHandleCast(const ArrayHandleCast<ValueType, ArrayHandleType> &src)
: SuperClass(src)
{ }
VTKM_ARRAY_HANDLE_SUBCLASS(
ArrayHandleCast,
(ArrayHandleCast<T, ArrayHandleType>),
(vtkm::cont::ArrayHandleTransform<
T,
ArrayHandleType,
internal::Cast<typename ArrayHandleType::ValueType, T> >));
VTKM_CONT_EXPORT
ArrayHandleCast(const ArrayHandleType &handle)
: SuperClass(handle)
: Superclass(handle)
{ }
VTKM_CONT_EXPORT
ArrayHandleCast(const vtkm::cont::ArrayHandle<ValueType, StorageTag> &src)
: SuperClass(src)
{ }
VTKM_CONT_EXPORT
virtual ~ArrayHandleCast() { }
};
/// make_ArrayHandleCast is convenience function to generate an

@ -278,6 +278,7 @@ struct ArrayHandleCompositeVectorTraits
typedef typename vtkm::internal::FunctionInterface<SignatureWithArrays>::ResultType
ValueType;
typedef vtkm::cont::internal::Storage<ValueType, Tag> StorageType;
typedef vtkm::cont::ArrayHandle<ValueType, Tag> Superclass;
};
// It may seem weird that this specialization throws an exception for
@ -482,9 +483,7 @@ private:
///
template<typename Signature>
class ArrayHandleCompositeVector
: public vtkm::cont::ArrayHandle<
typename internal::ArrayHandleCompositeVectorTraits<Signature>::ValueType,
typename internal::ArrayHandleCompositeVectorTraits<Signature>::Tag>
: public internal::ArrayHandleCompositeVectorTraits<Signature>::Superclass
{
typedef typename internal::ArrayHandleCompositeVectorTraits<Signature>::StorageType
StorageType;
@ -492,20 +491,10 @@ class ArrayHandleCompositeVector
ComponentMapType;
public:
typedef vtkm::cont::ArrayHandle<
typename internal::ArrayHandleCompositeVectorTraits<Signature>::ValueType,
typename internal::ArrayHandleCompositeVectorTraits<Signature>::Tag>
Superclass;
typedef typename Superclass::ValueType ValueType;
typedef typename Superclass::StorageTag StorageTag;
VTKM_CONT_EXPORT
ArrayHandleCompositeVector() : Superclass() { }
VTKM_CONT_EXPORT
ArrayHandleCompositeVector(const ArrayHandleCompositeVector<Signature> &src)
: Superclass(src)
{ }
VTKM_ARRAY_HANDLE_SUBCLASS(
ArrayHandleCompositeVector,
(ArrayHandleCompositeVector<Signature>),
(typename internal::ArrayHandleCompositeVectorTraits<Signature>::Superclass));
VTKM_CONT_EXPORT
ArrayHandleCompositeVector(
@ -514,12 +503,6 @@ public:
: Superclass(StorageType(arrays, sourceComponents))
{ }
VTKM_CONT_EXPORT
ArrayHandleCompositeVector(
const vtkm::cont::ArrayHandle<ValueType, StorageTag> &src)
: Superclass(src)
{ }
/// Template constructors for passing in types. You'll get weird compile
/// errors if the argument types do not actually match the types in the
/// signature.
@ -583,9 +566,6 @@ public:
sourceComponent3,
sourceComponent4)))
{ }
VTKM_CONT_EXPORT
virtual ~ArrayHandleCompositeVector() { }
};
/// \brief Get the type for an ArrayHandleCompositeVector

@ -59,33 +59,20 @@ template<typename T>
class ArrayHandleConstant
: public vtkm::cont::ArrayHandleImplicit<T, detail::ConstantFunctor<T> >
{
typedef vtkm::cont::ArrayHandleImplicit<T, detail::ConstantFunctor<T> >
Superclass;
public:
typedef typename Superclass::StorageTag StorageTag;
VTKM_ARRAY_HANDLE_SUBCLASS(
ArrayHandleConstant,
(ArrayHandleConstant<T>),
(vtkm::cont::ArrayHandleImplicit<T, detail::ConstantFunctor<T> >));
VTKM_CONT_EXPORT
ArrayHandleConstant(T value = T(), vtkm::Id numberOfValues = 0)
ArrayHandleConstant(T value, vtkm::Id numberOfValues = 0)
: Superclass(detail::ConstantFunctor<T>(value), numberOfValues) { }
VTKM_CONT_EXPORT
ArrayHandleConstant(const ArrayHandleConstant<T> &src)
: Superclass(src)
{ }
VTKM_CONT_EXPORT
ArrayHandleConstant(const vtkm::cont::ArrayHandle<T,StorageTag> &src)
: Superclass(src)
{ }
VTKM_CONT_EXPORT
virtual ~ArrayHandleConstant() { }
};
/// make_ArrayHandleImplicit is convenience function to generate an
/// ArrayHandleImplicit. It takes a functor and the virtual length of the
/// arry.
/// array.
///
template<typename T>
vtkm::cont::ArrayHandleConstant<T>

@ -109,13 +109,14 @@ class ArrayHandleCounting
typename internal::ArrayHandleCountingTraits<CountingValueType>::Tag
>
{
typedef vtkm::cont::ArrayHandle <
CountingValueType,
typename internal::ArrayHandleCountingTraits<CountingValueType>::Tag
> Superclass;
public:
typedef typename Superclass::ValueType ValueType;
typedef typename Superclass::StorageTag StorageTag;
VTKM_ARRAY_HANDLE_SUBCLASS(
ArrayHandleCounting,
(ArrayHandleCounting<CountingValueType>),
(vtkm::cont::ArrayHandle<
CountingValueType,
typename internal::ArrayHandleCountingTraits<CountingValueType>::Tag
>));
VTKM_CONT_EXPORT
ArrayHandleCounting(CountingValueType start,
@ -124,21 +125,6 @@ public:
:Superclass(typename Superclass::PortalConstControl(start, step, length))
{
}
VTKM_CONT_EXPORT
ArrayHandleCounting():Superclass() {}
VTKM_CONT_EXPORT
ArrayHandleCounting(const ArrayHandleCounting<CountingValueType> &src)
: Superclass(src)
{ }
VTKM_CONT_EXPORT
ArrayHandleCounting(const vtkm::cont::ArrayHandle<ValueType,StorageTag> &src)
: Superclass(src) { }
VTKM_CONT_EXPORT
virtual ~ArrayHandleCounting() { }
};
/// A convenience function for creating an ArrayHandleCounting. It takes the

@ -326,37 +326,23 @@ class ArrayHandleGroupVec
VTKM_IS_ARRAY_HANDLE(SourceArrayHandleType);
public:
typedef vtkm::cont::internal::StorageTagGroupVec<
SourceArrayHandleType, NUM_COMPONENTS> StorageTag;
VTKM_ARRAY_HANDLE_SUBCLASS(
ArrayHandleGroupVec,
(ArrayHandleGroupVec<SourceArrayHandleType, NUM_COMPONENTS>),
(vtkm::cont::ArrayHandle<
vtkm::Vec<typename SourceArrayHandleType::ValueType, NUM_COMPONENTS>,
vtkm::cont::internal::StorageTagGroupVec<
SourceArrayHandleType, NUM_COMPONENTS> >));
typedef typename SourceArrayHandleType::ValueType ComponentType;
typedef vtkm::cont::ArrayHandle<
vtkm::Vec<ComponentType,NUM_COMPONENTS>, StorageTag> Superclass;
typedef typename Superclass::ValueType ValueType;
private:
typedef vtkm::cont::internal::Storage<ValueType, StorageTag> StorageType;
public:
VTKM_CONT_EXPORT
ArrayHandleGroupVec() { }
VTKM_CONT_EXPORT
ArrayHandleGroupVec(
const ArrayHandleGroupVec<SourceArrayHandleType,NUM_COMPONENTS> &src)
: Superclass(src)
{ }
VTKM_CONT_EXPORT
ArrayHandleGroupVec(const SourceArrayHandleType &sourceArray)
: Superclass(StorageType(sourceArray)) { }
VTKM_CONT_EXPORT
ArrayHandleGroupVec(
const vtkm::cont::ArrayHandle<ValueType,StorageTag> &source)
: Superclass(source) { }
VTKM_CONT_EXPORT
virtual ~ArrayHandleGroupVec() { }
};
}

@ -85,6 +85,7 @@ struct ArrayHandleImplicitTraits
typedef vtkm::cont::StorageTagImplicit<
vtkm::cont::detail::ArrayPortalImplicit<ValueType,
FunctorType> > StorageTag;
typedef vtkm::cont::ArrayHandle<ValueType,StorageTag> Superclass;
};
} // namespace detail
@ -97,44 +98,24 @@ struct ArrayHandleImplicitTraits
/// The functor returns the result of the functor as the value of this
/// array at that position.
///
template <typename ValueType,
template <typename T,
class FunctorType>
class ArrayHandleImplicit
: public vtkm::cont::ArrayHandle <
ValueType,
typename detail::ArrayHandleImplicitTraits<ValueType,
FunctorType>::StorageTag >
: public detail::ArrayHandleImplicitTraits<T,FunctorType>::Superclass
{
private:
typedef typename detail::ArrayHandleImplicitTraits<ValueType,
FunctorType> ArrayTraits;
typedef typename detail::ArrayHandleImplicitTraits<T,FunctorType> ArrayTraits;
public:
typedef typename ArrayTraits::StorageTag StorageTag;
typedef vtkm::cont::ArrayHandle<ValueType,StorageTag> Superclass;
VTKM_CONT_EXPORT
ArrayHandleImplicit()
: Superclass(typename Superclass::PortalConstControl(FunctorType(),0)) { }
VTKM_CONT_EXPORT
ArrayHandleImplicit(const ArrayHandleImplicit<ValueType,FunctorType> &src)
: Superclass(src)
{ }
VTKM_ARRAY_HANDLE_SUBCLASS(
ArrayHandleImplicit,
(ArrayHandleImplicit<T,FunctorType>),
(typename ArrayTraits::Superclass));
VTKM_CONT_EXPORT
ArrayHandleImplicit(FunctorType functor, vtkm::Id length)
: Superclass(typename Superclass::PortalConstControl(functor,length))
{ }
VTKM_CONT_EXPORT
ArrayHandleImplicit(const vtkm::cont::ArrayHandle<ValueType,StorageTag> &src)
: Superclass(src)
{ }
VTKM_CONT_EXPORT
virtual ~ArrayHandleImplicit() { }
};
/// make_ArrayHandleImplicit is convenience function to generate an

@ -45,28 +45,14 @@ struct IndexFunctor {
class ArrayHandleIndex
: public vtkm::cont::ArrayHandleImplicit<vtkm::Id, detail::IndexFunctor>
{
typedef vtkm::cont::ArrayHandleImplicit<vtkm::Id, detail::IndexFunctor>
Superclass;
public:
typedef Superclass::ValueType ValueType;
typedef Superclass::StorageTag StorageTag;
VTKM_ARRAY_HANDLE_SUBCLASS_NT(
ArrayHandleIndex,
(vtkm::cont::ArrayHandleImplicit<vtkm::Id, detail::IndexFunctor>));
VTKM_CONT_EXPORT
ArrayHandleIndex(vtkm::Id length = 0)
ArrayHandleIndex(vtkm::Id length)
: Superclass(detail::IndexFunctor(), length) { }
VTKM_CONT_EXPORT
ArrayHandleIndex(const ArrayHandleIndex &src)
: Superclass(src)
{ }
VTKM_CONT_EXPORT
ArrayHandleIndex(const vtkm::cont::ArrayHandle<ValueType,StorageTag> &src)
: Superclass(src) { }
VTKM_CONT_EXPORT
virtual ~ArrayHandleIndex() { }
};
}

@ -370,37 +370,23 @@ class ArrayHandlePermutation
VTKM_IS_ARRAY_HANDLE(ValueArrayHandleType);
public:
typedef typename ValueArrayHandleType::ValueType ValueType;
VTKM_ARRAY_HANDLE_SUBCLASS(
ArrayHandlePermutation,
(ArrayHandlePermutation<IndexArrayHandleType,ValueArrayHandleType>),
(vtkm::cont::ArrayHandle<
typename ValueArrayHandleType::ValueType,
internal::StorageTagPermutation<
IndexArrayHandleType,ValueArrayHandleType> >));
typedef internal::StorageTagPermutation<IndexArrayHandleType, ValueArrayHandleType>
StorageTag;
private:
typedef vtkm::cont::internal::Storage<ValueType, StorageTag>
StorageType;
public:
typedef vtkm::cont::ArrayHandle<ValueType, StorageTag> Superclass;
VTKM_CONT_EXPORT
ArrayHandlePermutation() : Superclass( ) { }
VTKM_CONT_EXPORT
ArrayHandlePermutation(
const ArrayHandlePermutation<IndexArrayHandleType, ValueArrayHandleType> &src)
: Superclass(src)
{ }
VTKM_CONT_EXPORT
ArrayHandlePermutation(const IndexArrayHandleType &indexArray,
const ValueArrayHandleType &valueArray)
: Superclass(StorageType(indexArray, valueArray)) { }
VTKM_CONT_EXPORT
ArrayHandlePermutation(
const vtkm::cont::ArrayHandle<ValueType,StorageTag> &src)
: Superclass(src) { }
VTKM_CONT_EXPORT
virtual ~ArrayHandlePermutation() { }
};
/// make_ArrayHandleTransform is convenience function to generate an

@ -308,48 +308,32 @@ private:
/// the functor operator should work in both the control and execution
/// environments.
///
template <typename ValueType,
template <typename T,
typename ArrayHandleType,
typename FunctorType>
class ArrayHandleTransform
: public vtkm::cont::ArrayHandle<
ValueType,
internal::StorageTagTransform<ValueType, ArrayHandleType, FunctorType> >
T, internal::StorageTagTransform<T, ArrayHandleType, FunctorType> >
{
// If the following line gives a compile error, then the ArrayHandleType
// template argument is not a valid ArrayHandle type.
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
public:
typedef internal::StorageTagTransform<ValueType, ArrayHandleType, FunctorType>
StorageTag;
VTKM_ARRAY_HANDLE_SUBCLASS(
ArrayHandleTransform,
(ArrayHandleTransform<T,ArrayHandleType,FunctorType>),
(vtkm::cont::ArrayHandle<
T, internal::StorageTagTransform<T, ArrayHandleType, FunctorType> >));
private:
typedef vtkm::cont::internal::Storage<ValueType, StorageTag> StorageType;
public:
typedef vtkm::cont::ArrayHandle<ValueType, StorageTag> Superclass;
VTKM_CONT_EXPORT
ArrayHandleTransform() : Superclass( ) { }
VTKM_CONT_EXPORT
ArrayHandleTransform(
const ArrayHandleTransform<ValueType,ArrayHandleType,FunctorType> &src)
: Superclass(src)
{ }
public:
VTKM_CONT_EXPORT
ArrayHandleTransform(const ArrayHandleType &handle,
const FunctorType &functor = FunctorType())
: Superclass(StorageType(handle, functor)) { }
VTKM_CONT_EXPORT
ArrayHandleTransform(const vtkm::cont::ArrayHandle<ValueType,StorageTag> &src)
: Superclass(src) { }
VTKM_CONT_EXPORT
virtual ~ArrayHandleTransform() { }
};
/// make_ArrayHandleTransform is convenience function to generate an

@ -39,25 +39,17 @@ class ArrayHandleUniformPointCoordinates
vtkm::internal::ArrayPortalUniformPointCoordinates> >
{
public:
typedef vtkm::Vec<vtkm::FloatDefault,3> ValueType;
typedef vtkm::cont::StorageTagImplicit<
vtkm::internal::ArrayPortalUniformPointCoordinates> StorageTag;
typedef vtkm::cont::ArrayHandle<ValueType, StorageTag> Superclass;
VTKM_ARRAY_HANDLE_SUBCLASS_NT(
ArrayHandleUniformPointCoordinates,
(vtkm::cont::ArrayHandle<
vtkm::Vec<vtkm::FloatDefault,3>,
vtkm::cont::StorageTagImplicit<
vtkm::internal::ArrayPortalUniformPointCoordinates> >));
private:
typedef vtkm::cont::internal::Storage<ValueType, StorageTag> StorageType;
public:
VTKM_CONT_EXPORT
ArrayHandleUniformPointCoordinates() : Superclass() { }
VTKM_CONT_EXPORT
ArrayHandleUniformPointCoordinates(
const ArrayHandleUniformPointCoordinates &src)
: Superclass(src)
{ }
VTKM_CONT_EXPORT
ArrayHandleUniformPointCoordinates(
vtkm::Id3 dimensions,
@ -67,15 +59,6 @@ public:
StorageType(vtkm::internal::ArrayPortalUniformPointCoordinates(
dimensions, origin, spacing)))
{ }
VTKM_CONT_EXPORT
ArrayHandleUniformPointCoordinates(
const vtkm::cont::ArrayHandle<ValueType,StorageTag> &src)
: Superclass(src)
{ }
VTKM_CONT_EXPORT
virtual ~ArrayHandleUniformPointCoordinates() { }
};
}

@ -170,6 +170,10 @@ struct ArrayHandleZipTraits {
/// The appropriately templated tag.
///
typedef StorageTagZip<FirstHandleType,SecondHandleType> Tag;
/// The superclass for ArrayHandleZip.
///
typedef vtkm::cont::ArrayHandle<ValueType,Tag> Superclass;
};
@ -348,10 +352,7 @@ private:
template<typename FirstHandleType,
typename SecondHandleType>
class ArrayHandleZip
: public vtkm::cont::ArrayHandle<
typename internal::ArrayHandleZipTraits<FirstHandleType,SecondHandleType>::ValueType,
typename internal::ArrayHandleZipTraits<FirstHandleType,SecondHandleType>::Tag
>
: public internal::ArrayHandleZipTraits<FirstHandleType,SecondHandleType>::Superclass
{
// If the following line gives a compile error, then the FirstHandleType
// template argument is not a valid ArrayHandle type.
@ -362,36 +363,20 @@ class ArrayHandleZip
VTKM_IS_ARRAY_HANDLE(SecondHandleType);
public:
typedef typename internal::ArrayHandleZipTraits<FirstHandleType,
SecondHandleType>::ValueType ValueType;
typedef typename internal::ArrayHandleZipTraits<FirstHandleType,
SecondHandleType>::Tag StorageTag;
typedef vtkm::cont::ArrayHandle<ValueType, StorageTag> Superclass;
VTKM_ARRAY_HANDLE_SUBCLASS(
ArrayHandleZip,
(ArrayHandleZip<FirstHandleType,SecondHandleType>),
(typename internal::ArrayHandleZipTraits<
FirstHandleType,SecondHandleType>::Superclass));
private:
typedef vtkm::cont::internal::Storage<ValueType, StorageTag> StorageType;
public:
VTKM_CONT_EXPORT
ArrayHandleZip() : Superclass( ) { }
VTKM_CONT_EXPORT
ArrayHandleZip(const ArrayHandleZip<FirstHandleType,SecondHandleType> &src)
: Superclass(src)
{ }
VTKM_CONT_EXPORT
ArrayHandleZip(const FirstHandleType &firstArray,
const SecondHandleType &secondArray)
: Superclass( StorageType( firstArray, secondArray ) ) { }
VTKM_CONT_EXPORT
ArrayHandleZip(const vtkm::cont::ArrayHandle<ValueType, StorageTag> &src)
: Superclass(src) { }
VTKM_CONT_EXPORT
virtual ~ArrayHandleZip() { }
};
/// A convenience function for creating an ArrayHandleZip. It takes the two