% -*- latex -*-

\chapter{Variant Array Handles}
\label{chap:VariantArrayHandle}

\index{variant array handle|(}
\index{array handle!variant|(}

The \textidentifier{ArrayHandle} class uses templating to make very
efficient and type-safe access to data. However, it is sometimes
inconvenient or impossible to specify the element type and storage at
run-time. The \textidentifier{VariantArrayHandle} class provides a mechanism
to manage arrays of data with unspecified types.

\vtkmcont{VariantArrayHandle} holds a reference to an array. Unlike
\textidentifier{ArrayHandle}, \textidentifier{VariantArrayHandle} is
\emph{not} templated. Instead, it uses C++ run-type type information to
store the array without type and cast it when appropriate.

\index{variant array handle!construct}
A \textidentifier{VariantArrayHandle} can be established by constructing it
with or assigning it to an \textidentifier{ArrayHandle}. The following
example demonstrates how a \textidentifier{VariantArrayHandle} might be
used to load an array whose type is not known until run-time.

\vtkmlisting{Creating a \textidentifier{VariantArrayHandle}.}{CreateVariantArrayHandle.cxx}

\section{Querying and Casting}
\label{sec:VariantArrayHandleQueryingAndCasting}

\index{variant array handle!query}
Data pointed to by a \textidentifier{VariantArrayHandle} is not directly
accessible. However, there are a few generic queries you can make without
directly knowing the data type. The \classmember*{VariantArrayHandle}{GetNumberOfValues} method
returns the length of the array with respect to its base data type. It is
also common in \VTKm to use data types, such as \vtkm{Vec}, with multiple
components per value. The \classmember*{VariantArrayHandle}{GetNumberOfComponents} method returns
the number of components in a vector-like type (or 1 for scalars).

\vtkmlisting{Non type-specific queries on \textidentifier{VariantArrayHandle}.}{NonTypeQueriesVariantArrayHandle.cxx}

\index{variant array handle!new instance}
It is also often desirable to create a new array based on the underlying
type of a \textidentifier{VariantArrayHandle}. For example, when a filter
creates a field, it is common to make this output field the same type as
the input. To satisfy this use case, \textidentifier{VariantArrayHandle}
has a method named \classmember*{VariantArrayHandle}{NewInstance} that creates a new empty array
with the same underlying type as the original array.

\vtkmlisting{Using \textcode{NewInstance}.}{VariantArrayHandleNewInstance.cxx}

Before the data with a \textidentifier{VariantArrayHandle} can be accessed,
the type of the array must be established. This is usually done
internally within \VTKm when a worklet or filter is invoked and the \textidentifier{VariantArrayHandle}
is converted into an \textidentifier{ArrayHandleVirtual}.
However, it is also possible to query the types and cast to a concrete
\textidentifier{ArrayHandle}.

\index{variant array handle!query}
You can query the component type using the \classmember{VariantArrayHandle}{IsValueType} method. 
\classmember*{VariantArrayHandle}{IsValueType} takes a value type and returns whether that matches the
underlying array. You can query the component type and storage type using the
\classmember{VariantArrayHandle}{IsType} method. \classmember*{VariantArrayHandle}{IsType} takes an
example array handle type and returns whether the underlying array matches
the given static array type.

\vtkmlisting{Querying the component and storage types of a \textidentifier{VariantArrayHandle}.}{QueryVariantArrayHandle.cxx}

\index{variant array handle!cast}
Once the type of the \textidentifier{VariantArrayHandle} is known, it can
be cast to either to \textidentifier{ArrayHandleVirtual} or a concrete 
\textidentifier{ArrayHandle}, which has access to the data as described in 
Chapter~\ref{chap:AccessingAllocatingArrays}. The easiest ways to do this is to use
\classmember*{VariantArrayHandle}{AsVirtual} when desiring an \textidentifier{ArrayHandleVirtual} 
or \classmember*{VariantArrayHandle}{CopyTo} method  when wanting a concrete \textidentifier{ArrayHandle}. 

The \classmember{VariantArrayHandle}{AsVirtual} templated method takes a
value type as a template parameter and returns an
array handle virtual that points to the array in \textidentifier{VariantArrayHandle}.
If the given types are incorrect, then \classmember*{VariantArrayHandle}{AsVirtual} throws
a \vtkmcont{ErrorControlBadValue} exception.

\vtkmlisting{Casting a \textidentifier{VariantArrayHandle} to a virtual
  \textidentifier{ArrayHandle}.}{AsVirtualVariantArrayHandle.cxx}

The \classmember{VariantArrayHandle}{CopyTo} templated method takes a
reference to an \textidentifier{ArrayHandle} as an argument and sets that
array handle to point to the array in \textidentifier{VariantArrayHandle}.
If the given types are incorrect, then \classmember*{VariantArrayHandle}{CopyTo} throws
a \vtkmcont{ErrorControlBadValue} exception.

\vtkmlisting{Casting a \textidentifier{VariantArrayHandle} to a concrete
  \textidentifier{ArrayHandle}.}{CastVariantArrayHandle.cxx}

\begin{commonerrors}
  Remember that \textidentifier{ArrayHandle} and
  \textidentifier{VariantArrayHandle} represent pointers to the data, so
  this ``copy'' is a shallow copy. There is still only one copy of the
  data, and if you change the data in one array handle that change is
  reflected in the other. 
\end{commonerrors}

\section{Casting to Unknown Types}

\index{variant array handle!cast|(}

Using \classmember*{VariantArrayHandle}{AsVirtual}, and \classmember*{VariantArrayHandle}{CopyTo} are fine as long as the 
correct types are known, but often times they are not. For this use case
\textidentifier{VariantArrayHandle} has a method named
\classmember*{VariantArrayHandle}{CastAndCall} that attempts to cast the array to some set of
types.

The \classmember*{VariantArrayHandle}{CastAndCall} method accepts a functor to run on the
appropriately cast array. The functor must have an overloaded const
parentheses operator that accepts an \textidentifier{ArrayHandle} of the
appropriate type.

\vtkmlisting[ex:UsingCastAndCall]{Operating on \textidentifier{VariantArrayHandle} with \textcode{CastAndCall}.}{UsingCastAndCall.cxx}

\begin{commonerrors}
  It is possible to store any form of \textidentifier{ArrayHandle} in a
  \textidentifier{VariantArrayHandle}, but it is not possible for
  \classmember*{VariantArrayHandle}{CastAndCall} to check every possible form of
  \textidentifier{ArrayHandle}. If \classmember*{VariantArrayHandle}{CastAndCall} cannot determine
  the \textidentifier{ArrayHandle} type, then an
  \textidentifier{ErrorControlBadValue} is thrown. The following section
  describes how to specify the forms of \textidentifier{ArrayHandle} to try.
\end{commonerrors}

\section{Specifying Cast Lists}
\label{sec:VariantArrayHandleSpecifyingCastLists}

The \classmember*{VariantArrayHandle}{CastAndCall} method can only check a finite number of value types.
The default form of \classmember*{VariantArrayHandle}{CastAndCall} uses a default set of common
types. These default lists can be overridden using the \VTKm lists
facility, which is discussed at length in Section~\ref{sec:ListTemplate}.

Common type lists for value are defined in
\vtkmheader{vtkm}{TypeList.h} and are documented in
Section~\ref{sec:TypeLists}. This header also defines
\vtkmmacro{VTKM\_DEFAULT\_TYPE\_LIST}, which defines the default list
of value types tried in \classmember*{VariantArrayHandle}{CastAndCall}.

There is a form of \classmember*{VariantArrayHandle}{CastAndCall} that accepts a tag for the list of
component types. This can be used when the specific list is known at the time of
the call. However, when creating generic operations like the \classmember*{VariantArrayHandle}{PrintArrayContents}
function in Example~\ref{ex:UsingCastAndCall}, passing these tag is inconvenient at
best.

To address this use case, \textidentifier{VariantArrayHandle} has a method
named \classmember*{VariantArrayHandle}{ResetTypes}. This method returns a new object that
behaves just like a \textidentifier{VariantArrayHandle} with identical
state except that the cast and call functionality uses the specified
component types instead of the default. (Note that
\classmember*{VariantArrayHandle}{PrintArrayContents} in Example~\ref{ex:UsingCastAndCall} is
templated on the type of \textidentifier{VariantArrayHandle}. This is to
accommodate using the objects from the \textcode{ResetTypes} method, which
have the same behavior but different type names.)

So the default component type list contains a subset of the basic \VTKm
types. If you wanted to accommodate more types, you could use
\classmember*{VariantArrayHandle}{ResetTypes}.

\vtkmlisting{Trying all component types in a \textidentifier{VariantArrayHandle}.}{CastAndCallAllTypes.cxx}

Likewise, if you happen to know a particular type of the variant array,
that can be specified to reduce the amount of object code created by
templates in the compiler.

\vtkmlisting{Specifying a single component type in a \textidentifier{VariantArrayHandle}.}{CastAndCallSingleType.cxx}

\begin{commonerrors}
  \classmember{VariantArrayHandle}{ResetTypes} does not change the object. Rather, it returns a 
  new object with different type information. This method has no effect
  unless you do something with the returned value.
\end{commonerrors}

\classmember*{VariantArrayHandle}{ResetTypes} works by
returning a \vtkmcont{VariantArrayHandleBase} object.
\textidentifier{VariantArrayHandleBase} specifies the value tag as a template
argument and otherwise behaves just like \textidentifier{VariantArrayHandle}.

\begin{didyouknow}
  I lied earlier when I said at the beginning of this chapter that
  \textidentifier{VariantArrayHandle} is a class that is not templated.
  This symbol is really just a type alias of
  \textidentifier{VariantArrayHandleBase}. Because the
  \textidentifier{VariantArrayHandle} fully specifies the template
  arguments, it behaves like a class, but if you get a compiler error it
  will show up as \textidentifier{VariantArrayHandleBase}.
\end{didyouknow}

Most code does not need to worry about working directly with
\textidentifier{VariantArrayHandleBase}. However, it is sometimes useful to
declare it in templated functions that accept variant array handles so that
works with every type list. The function in
Example~\ref{ex:UsingCastAndCall} did this by making the variant array
handle class itself the template argument. This will work, but it is prone
to error because the template will resolve to any type of argument. When
passing objects that are not variant array handles will result in strange
and hard to diagnose errors. Instead, we can define the same function using
\textidentifier{VariantArrayHandleBase} so that the template will only match
variant array handle types.

\vtkmlisting{Using \textidentifier{VariantArrayHandleBase} to accept generic variant array handles.}{VariantArrayHandleBase.cxx}


\index{variant array handle!cast|)}

\index{array handle!variant|)}
\index{variant array handle|)}
