Currently, ListTags are implemented by having a subtype name list set to
a brigand::list. However, there is always a chance this will change. To
make things more explicit, create a vtkm::internal::ListTagToBrigandList
to make it clear what the resulting type should be (and provide some
potential future-proofing).
Also add a convenient vtkm::ListTagApply that allows you to easily
instantiate a template with the list of types in a ListTag.
E.g:
```
ArrayHandle<Float64> doubleArray;
VariantArrayHandle varHandle{doubleArray};
ArrayHandleVirtual<Float32> = varHandle.AsVirtual<Float32>();
```
If there is a loss in range and/or precision, a warning is logged. If
the ValueTypes are Vecs with mismatched widths, an ErrorBadType is thrown.
Internally, an ArrayHandleCast is used between the VariantArrayHandle's
stored array and the ArrayHandleVirtual.
When you call VariantArrayHandle::CastAndCall, it now tries both basic
storage and virtual storage. You can modify the types of storages tried
by giving a type list of storage tags as the first argument.
ArrayHandleVirtual can automatically be constructed from any ArrayHandle.
In the cases where the input ArrayHandle doesn't derived from ArrayHandleVirtual,
it will automatically construct StorageAny to hold the array.