% -*- 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{ArrayHandle}.
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}
\index{variant array handle!AsArrayHandle}
Once the type of the \textidentifier{VariantArrayHandle} is known, it can
be cast to 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 the
\classmember*{VariantArrayHandle}{AsArrayHandle} method.

The \classmember{VariantArrayHandle}{AsArrayHandle} 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}{AsArrayHandle} throws
a \vtkmcont{ErrorControlBadValue} exception.

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

\classmember{VariantArrayHandle}{AsArrayHandle} also has an overload that takes no arguments and returns an \textidentifier{ArrayHandle} of the requested type.
For this form of \classmember*{VariantArrayHandle}{AsArrayHandle} you have to specify the type of \textidentifier{ArrayHandle} using a template argument.
This form is particularly useful when passing the value immediately to a function or method.

\vtkmlisting{Casting a \textidentifier{VariantArrayHandle} to a concrete \textidentifier{ArrayHandle} without using a temporary variable.}{CastVariantArrayHandleDirect.cxx}

\classmember{VariantArrayHandle}{AsArrayHandle} treats cast arrays specially.
If you request an array of type \vtkmcont{ArrayHandleCast}, the call will succeed as long as the \textidentifier{VariantArrayHandle} is holding the array to be cast.
In the following example, the call to \classmember*{VariantArrayHandle}{AsArrayHandle} succeeds if the \textidentifier{VariantArrayHandle} is holding a basic \textidentifier{ArrayHandle} of type \vtkm{Float32}.

\vtkmlisting{Getting an array of \textidentifier{Float32} from \textidentifier{VariantArrayHandle} cast to \textidentifier{Float64}.}{VariantArrayHandleCastArray.cxx}

If you can narrow down the types of arrays stored in a \textidentifier{VariantArrayHandle} to some finite list of types and want to use it as a normal \textidentifier{ArrayHandle}, you can use the \classmember*{VariantArrayHandle}{AsArrayHandle} method to get the array as an \vtkmcont{ArrayHandleMultiplexer}.
If the \textidentifier{VariantArrayHandle} holds an array of any type that can be represented by the provided \textidentifier{ArrayHandleMultiplexer}, then \classmember*{VariantArrayHandle}{AsArrayHandle} will return with the \textidentifier{ArrayHandleMultiplexer} holding the array.
This allows you to run algorithms on the array that will behave correctly for any of the given types.
If the \textidentifier{VariantArrayHandle} actually holds an array that is not representable by the \textidentifier{ArrayHandleMultiplexer}, a \vtkmcont{ErrorControlBadType} exception will be thrown.

\vtkmlisting[ex:AsMultiplexerVariantArrayHandle.cxx]{Getting an array from \textidentifier{VariantArrayHandle} as a \textidentifier{ArrayHandleMultiplexer}}{AsMultiplexerVariantArrayHandle.cxx}

\begin{didyouknow}
  If using \classmember{VariantArrayHandle}{AsArrayHandle} with an \textidentifier{ArrayHandleMultiplexer} that itself can hold arrays of type \textidentifier{ArrayHandleCast}, then \classmember*{VariantArrayHandle}{AsArrayHandle} will properly fill the \textidentifier{ArrayHandleMultiplexer} with an array that is being cast.
  For example, if the \textidentifier{VariantArrayHandle} in Example \ref{ex:AsMultiplexerVariantArrayHandle.cxx} contains an array of type \textidentifier{ArrayHandle}\tparams{\vtkm{Float64}}, then that array will be placed in a \textidentifier{ArrayHandleCast} to convert it to an array of type \vtkm{Float32}, and that will be placed in the resulting \textidentifier{ArrayHandleMultiplexer}.
  This allows you to treat an array of known storage but unknown value type as a single type of array.
\end{didyouknow}

\section{Casting to Unknown Types}

\index{variant array handle!cast|(}

Using \classmember*{VariantArrayHandle}{AsArrayHandle} is 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|)}
