The `VecTraits` class allows templated functions, methods, and classes to
treat type arguments uniformly as `Vec` types or to otherwise differentiate
between scalar and vector types. This only works for types that `VecTraits`
is defined for.
The `VecTraits` templated class now has a default implementation that will
be used for any type that does not have a `VecTraits` specialization. This
removes many surprise compiler errors when using a template that, unknown
to you, has `VecTraits` in its implementation.
One potential issue is that if `VecTraits` gets defined for a new type, the
behavior of `VecTraits` could change for that type in backward-incompatible
ways. If `VecTraits` is used in a purely generic way, this should not be an
issue. However, if assumptions were made about the components and length,
this could cause problems.
Fixes#589
You can often get compile errors when trying to get `Vec` attributes
from types that do not define `VecTraits`. This is of particular problem
when you create an object like `Vec` with a component that does not
define `VecTraits`. Make using these types safer by internally using
`SafeVecTraits`, which will gracefully handle types that do not have
`VecTraits`.
`VecFlat` has a casting operator to cast itself to the nested version of
the `Vec`. However, for a simple `Vec` type, the superclass of `VecFlat`
is the same type as the "nested" `Vec` type (which was flat to begin
with). This meant that the casting operator was never used because it
casted to the same type as the object being cast from. Most compilers
silently ignored this, but some gave a warning that the casting operator
would never be used because of this condition.
Fix the problem by having a different implemention of `VecFlat` when
applied to a `Vec` that is already flat.
`vtkm::VecFlat` is a wrapper around a `Vec`-like class that may be a
nested series of vectors. For example, if you run a gradient operation
on a vector field, you are probably going to get a `Vec` of `Vec`s that
looks something like `vtkm::Vec<vtkm::Vec<vtkm::Float32, 3>, 3>`. That
is fine, but what if you want to treat the result simply as a `Vec` of
size 9?
The `VecFlat` wrapper class allows you to do this. Simply place the
nested `Vec` as an argument to `VecFlat` and it will behave as a flat
`Vec` class. (In fact, `VecFlat` is a subclass of `Vec`.) The `VecFlat`
class can be copied to and from the nested `Vec` it is wrapping.
There is a `vtkm::make_VecFlat` convenience function that takes an
object and returns a `vtkm::VecFlat` wrapped around it.