[vtk-developers] Alternatives to vtkTemplateMacro
Timothy M. Shead
tshead at sandia.gov
Mon Sep 14 17:09:33 EDT 2009
Moreland, Kenneth wrote:
> The use case I am most worried about, because the use is very common,
is a functor that needs to take two arrays that have the same type.
Typically this happens when you take an input array and use that data to
construct an output array. You know they are the same type because you
made the output array. To implement that right now, you have to pass one
of the arrays as a field to the functor class, call the functor with the
other array, and then do a type cast on the array. I argue that this is
awkward to code and read. There should be a mechanism to define a
functor that takes two typed arrays instead of one.
> Now for the difference between the two so far proposed methods
for simplicity, I will call Tim’s method and Brad’s method). As usual,
Brad’s solution is so clever that it takes me a long time just to
understand all the cool magic things it does under the covers to make my
life easier. If I understand it correctly, the “issue” with Tim’s method
is that the functor has to implement every possible type supported by
the Apply method. Even in Tim’s simple examples, the functor has to
implement string versions of the function even though they are no-ops
because they don’t do anything. In Brad’s method, you can simply
implement the types you feel you need to support.
> The thing I don’t like about Brad’s methods is that it adds more
to the process. First you have to implement the functor (much like Tim’s
method), then you have to create an apply_map and tell the map all the
types your functor you support (which you have pretty much already
specified when you declared the functor in the first place). I admit,
mostly this is just an annoyance (remember, I like vtkTemplateMacro
because all I need to do is define a templated function). But there is
also an increased potential for errors. If you forget to (or
inappropriately) define a type for a functor, then the compiler will
give lots of nasty errors. However, if you forget to specify one of the
types for the apply_map, then it will silently fail, perhaps some time
later in the future because you forgot to test that type.
> I think the issue of having the functor implement types it does not
really support could be addressed with Tim’s method by simply offering
specialized versions of Apply that only work on some subset of the
possible types. For example, a version of Apply that only downcast to
numeric types would probably cover the majority of the cases.
> As far as the double dispatch is concerned, I’m not sure why you
implement that by having a templated functor with an internal templated
functor that worked with the other type. That is basically how you
implement double dispatch with the current vtkTemplateMacro.
Kudos to Brad for calling-out the double-dispatch nature of the problem.
That said, I agree with Ken that you could probably cover 95% of your
use-cases with a couple of scenarios:
1) Filters that accept input arrays of any type, and produce output
arrays of the same type.
2) Filters that accept input arrays from a set of types (say, all
numeric array types), and produce output arrays of one specific type.
To handle case 1), vtkArray already has a DeepCopy() method that can be
used by a filter to create a new output array with the same type and
contents as an input array. For cases where you want to create an array
with the same type, but avoid doing any copying, NewInstance() should do
the trick. I could imagine making this part of the proposed Apply()
method, or part of a similar, related template algorithm.
To handle case 2), my assumption is that a filter author is creating the
output array that they want, so it can simply be a parameter in the
That leaves the issue of explicitly specifying which concrete array
types need to be handled in the caller's functor. The Apply<> template
could be parameterized using typelists to handle this, and I could
imagine providing some preset typelists for e.g. "all types", "numeric
types", "string types", and-so-on. The nice thing about this approach
is that callers could define their own typelists if they needed - "all
integer types" for example.
More information about the vtk-developers