You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
215 lines
7.6 KiB
C++
215 lines
7.6 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkDispatcher.h
|
|
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notice for more information.
|
|
|
|
=========================================================================*/
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// The Loki Library
|
|
// Copyright (c) 2001 by Andrei Alexandrescu
|
|
// This code accompanies the book:
|
|
// Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
|
|
// Patterns Applied". Copyright (c) 2001. Addison-Wesley.
|
|
// Permission to use, copy, modify, distribute and sell this software for any
|
|
// purpose is hereby granted without fee, provided that the above copyright
|
|
// notice appear in all copies and that both that copyright notice and this
|
|
// permission notice appear in supporting documentation.
|
|
// The author or Addison-Wesley Longman make no representations about the
|
|
// suitability of this software for any purpose. It is provided "as is"
|
|
// without express or implied warranty.
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* @class vtkDispatcher
|
|
* @brief Dispatch to functor based on a pointer type.
|
|
*
|
|
* vtkDispatcher is a class that allows calling a functor based
|
|
* on the derived types of a pointer. This form of dynamic dispatching
|
|
* allows the conversion of runtime polymorphism to a compile time polymorphism.
|
|
* For example it can be used as a replacement for the vtkTemplateMacro, with
|
|
* bonus of being easier to understand
|
|
*
|
|
* Note: By default the return type is void.
|
|
*
|
|
* The functors that are passed around can contain state, and are allowed
|
|
* to be const or non const. If you are using a functor that does have state,
|
|
* make sure your copy constructor is correct.
|
|
*
|
|
* \code
|
|
* struct functor{
|
|
* template<typename T>
|
|
* void operator()(T& t) const
|
|
* {
|
|
*
|
|
* }
|
|
* };
|
|
*
|
|
* Here is an example of using the dispatcher.
|
|
* \code
|
|
* statefull functor;
|
|
* vtkDispatcher<vtkDataArray> dispatcher;
|
|
* dispatcher.Add<vtkCharArray>(&functor);
|
|
* dispatcher.Add<vtkDoubleArray>(&functor);
|
|
* dispatcher.Add<vtkIdTypeArray>(&functor);
|
|
* dispatcher.Add<vtkIntArray>(&functor);
|
|
* dispatcher.Add<vtkFloatArray>(&functor);
|
|
* dispatcher.Go(ptr1);
|
|
* \endcode
|
|
*
|
|
*
|
|
* @sa
|
|
* vtkDispatcher
|
|
*/
|
|
|
|
#ifndef vtkDispatcher_h
|
|
#define vtkDispatcher_h
|
|
|
|
#include "vtkConfigure.h"
|
|
|
|
#ifndef VTK_LEGACY_REMOVE
|
|
|
|
#include "vtkDispatcher_Private.h" //needed for Functor,CastingPolicy,TypeInfo
|
|
#include <map> //Required for the storage of template params to runtime params
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// class template FunctorDispatcher
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
template <class BaseLhs, typename ReturnType = void,
|
|
template <class, class> class CastingPolicy = vtkDispatcherCommon::vtkCaster>
|
|
class vtkDispatcher
|
|
{
|
|
public:
|
|
/**
|
|
* Add in a functor that is mapped to the template SomeLhs parameter.
|
|
* When instances of the parameter is passed in on the Go method we will call
|
|
* the functor and pass along the given parameter.
|
|
* Note: This copies the functor so pass stateful functors by pointer.
|
|
|
|
* \code
|
|
* vtkDispatcher<vtkDataModel> dispatcher;
|
|
* dispatcher.Add<vtkImageData>(exampleFunctor());
|
|
* dispatcher.Add<vtkImageData>(&exampleFunctorWithState);
|
|
* \endcode
|
|
*/
|
|
template <class SomeLhs, class Functor>
|
|
void Add(Functor fun)
|
|
{
|
|
VTK_LEGACY_BODY(vtkDispatcher, "VTK 9.0");
|
|
this->AddInternal<SomeLhs>(fun, 1);
|
|
}
|
|
|
|
/**
|
|
* Remove a functor that is bound to the given parameter type. Will
|
|
* return true if we did remove a functor.
|
|
*/
|
|
template <class SomeLhs>
|
|
bool Remove()
|
|
{
|
|
return DoRemove(typeid(SomeLhs));
|
|
}
|
|
|
|
/**
|
|
* Given a pointer to an object that derives from the BaseLhs
|
|
* we find the matching functor that was added, and call it passing along
|
|
* the given parameter. It should be noted that the functor will be called
|
|
* with the parameter being the derived type that Functor was registered with.
|
|
|
|
* Note: This will only find exact matches. So if you add functor to find
|
|
* vtkDataArray, it will not be called if passed with a vtkDoubleArray.
|
|
|
|
* \code
|
|
|
|
* vtkDispatcher<vtkDataArray> dispatcher;
|
|
* dispatcher.Add(vtkFloatArray>(floatFunctor())
|
|
* dispatcher.Add(vtkDoubleArray>(doubleFunctor())
|
|
* dispatcher.Go(dataArray1);
|
|
* dispatcher.Go(dataArray2);
|
|
* \endcode
|
|
*/
|
|
ReturnType Go(BaseLhs* lhs);
|
|
|
|
protected:
|
|
typedef vtkDispatcherCommon::TypeInfo TypeInfo;
|
|
typedef vtkDispatcherPrivate::Functor<ReturnType, BaseLhs> MappedType;
|
|
|
|
void DoAddFunctor(TypeInfo lhs, MappedType fun);
|
|
bool DoRemove(TypeInfo lhs);
|
|
typedef std::map<TypeInfo, MappedType> MapType;
|
|
MapType FunctorMap;
|
|
|
|
private:
|
|
template <class SomeLhs, class Functor>
|
|
void AddInternal(Functor const& fun, long);
|
|
template <class SomeLhs, class Functor>
|
|
void AddInternal(Functor* fun, int);
|
|
};
|
|
|
|
// We are making all these method non-inline to reduce compile time overhead
|
|
//----------------------------------------------------------------------------
|
|
template <class BaseLhs, typename ReturnType, template <class, class> class CastingPolicy>
|
|
template <class SomeLhs, class Functor>
|
|
void vtkDispatcher<BaseLhs, ReturnType, CastingPolicy>::AddInternal(const Functor& fun, long)
|
|
{
|
|
typedef vtkDispatcherPrivate::FunctorDispatcherHelper<BaseLhs, SomeLhs, ReturnType,
|
|
CastingPolicy<SomeLhs, BaseLhs>, Functor>
|
|
Adapter;
|
|
Adapter ada(fun);
|
|
MappedType mt(ada);
|
|
DoAddFunctor(typeid(SomeLhs), mt);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
template <class BaseLhs, typename ReturnType, template <class, class> class CastingPolicy>
|
|
template <class SomeLhs, class Functor>
|
|
void vtkDispatcher<BaseLhs, ReturnType, CastingPolicy>::AddInternal(Functor* fun, int)
|
|
{
|
|
typedef vtkDispatcherPrivate::FunctorRefDispatcherHelper<BaseLhs, SomeLhs, ReturnType,
|
|
CastingPolicy<SomeLhs, BaseLhs>, Functor>
|
|
Adapter;
|
|
Adapter ada(*fun);
|
|
MappedType mt(ada);
|
|
DoAddFunctor(typeid(SomeLhs), mt);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
template <class BaseLhs, typename ReturnType, template <class, class> class CastingPolicy>
|
|
void vtkDispatcher<BaseLhs, ReturnType, CastingPolicy>::DoAddFunctor(TypeInfo lhs, MappedType fun)
|
|
{
|
|
FunctorMap[TypeInfo(lhs)] = fun;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
template <class BaseLhs, typename ReturnType, template <class, class> class CastingPolicy>
|
|
bool vtkDispatcher<BaseLhs, ReturnType, CastingPolicy>::DoRemove(TypeInfo lhs)
|
|
{
|
|
return FunctorMap.erase(TypeInfo(lhs)) == 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
template <class BaseLhs, typename ReturnType, template <class, class> class CastingPolicy>
|
|
ReturnType vtkDispatcher<BaseLhs, ReturnType, CastingPolicy>::Go(BaseLhs* lhs)
|
|
{
|
|
typename MapType::key_type k(typeid(*lhs));
|
|
typename MapType::iterator i = FunctorMap.find(k);
|
|
if (i == FunctorMap.end())
|
|
{
|
|
// we return a default type, currently i don't want exceptions thrown
|
|
return ReturnType();
|
|
}
|
|
return (i->second)(*lhs);
|
|
}
|
|
|
|
#endif // legacy
|
|
|
|
#endif // vtkDispatcher_h
|
|
// VTK-HeaderTest-Exclude: vtkDispatcher.h
|