[vtk-developers] Alternatives to vtkTemplateMacro

Brad King brad.king at kitware.com
Mon Sep 21 14:08:56 EDT 2009


Timothy M. Shead wrote:
> Sounds reasonable, although Apply would still only work with vtkObject
> derivatives that are templated on something.  To my knowledge,
> vtkTypedArray<> derivatives are the only classes that match this
> criteria, i.e. if we want to make Apply usable with vtkAbstractArray,
> that'll involve additional work.

With real RTTI we could use dynamic_cast to support any type.

> I'm not in love with the aesthetics of this approach
> ... for someone looking at the implementation of a filter,
> 
> if(!vtkApply<vtkNumericTypes, vtkTypedArray>(functor, array))
>   vtkErrorMacro("First operand array must be a numeric type");
> 
> seems clearer than
> 
> if(!vtkApply(functor, array))
>   vtkErrorMacro("First operand array must be a numeric type");
> 
> to me.  It's also the case that a functor with templated operators might
> be applied to different typelists at different times, so specifying the
> typelist in the algorithm provides a little extra flexibility.

Agreed.

> There are a couple other dimensions to the design that I'm looking into,
> first is whether we should allow additional arguments to be passed to
> the functor by the caller; although callers can make their functors as
> complex as they like, Ken makes the observation that it would be nice to
> be able to pass parameters to a functor without having to write all the
> boilerplate that that entails (creating a constructor, declaring storage
> for each parameter, etc).

I have no strong opinion either way on this, but I have a suggestion.
I think for VTK filters we might get away with just storing a pointer
to the filter object in the functor:

  vtkApply<...>(my_functor(this), array)

Then the functor can just ask the filter for whatever it needs.

Actually, perhaps for VTK the functor should be a glorified
pimpl-idiom:

  // vtkMyFilter.h
  class vtkMyFilter: public vtkAlgorithm
  {
    ...
    class Internal;
    friend class Internal;
  };

  // vtkMyFilter.cxx
  class vtkMyFilter::Internal
  {
  public:
    Internal(vtkMyFilter* external): External(external) {}
    vtkMyFilter* External;

    template <class T>
    void operator()(vtkTypedArray<T>&) { ... }
  };

The purpose of vtkApply is simply to replace vtkTemplateMacro,
and the Internal object takes the place of the template passed
to vtkTemplateMacro.  The "functor" is already constructed and
has full access to parameters.

> Second, there's the question of what vtkApply would return.  One option
> is a bool to indicate whether any of the types in the typelist matched,
> which is straightforward and would be useful in many cases.  Second
> option is return a copy of the functor, which would be consistent with
> many standard library algorithms, and would allow the functor to return
> arbitrary results to the caller.

I like the idea of returning the functor.  It is elegant, especially
if this is used in a non-filter context.

This leaves the question of what to do when no suitable implementation
is available for the arguments given.  VTK is not exception-friendly.
Brainstorming:

1.) Require functors to have a valid "not-run" state
    that can be detected upon return of the dispatcher.

2.) Require functors to provide an error method, or ask the
    user to pass in a second error-handling functor.

3.) Actually run vtkErrorMacro from vtkApply.

4.) Choose among other options based on arguments passed.

5.) Use exceptions and require all vtkApply calls to be
    try/catch-ed or otherwise made exception safe locally.

> In case anyone wants to play around with this / look at the syntax,
> I hacked-together some sample code in
> VTK/Common/Testing/Cxx/ArrayCasting.cxx.

That looks like a good start.

-Brad



More information about the vtk-developers mailing list