/*========================================================================= Program: Visualization Toolkit Module: vtkArrayDispatch.txx 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. =========================================================================*/ #ifndef vtkArrayDispatch_txx #define vtkArrayDispatch_txx #include "vtkArrayDispatch.h" #include "vtkConfigure.h" // For warning macro settings. #include "vtkSetGet.h" // For warning macros. #include // For std::forward class vtkDataArray; namespace vtkArrayDispatch { namespace impl { //------------------------------------------------------------------------------ // Implementation of the single-array dispatch mechanism. template struct Dispatch; // Terminal case: template <> struct Dispatch { template static bool Execute(T&&...) { #ifdef VTK_WARN_ON_DISPATCH_FAILURE vtkGenericWarningMacro("Array dispatch failed."); #endif return false; } }; // Recursive case: template struct Dispatch > { template static bool Execute(vtkDataArray* inArray, Worker&& worker, Params&&... params) { if (ArrayHead* array = vtkArrayDownCast(inArray)) { worker(array, std::forward(params)...); return true; } else { return Dispatch::Execute( inArray, std::forward(worker), std::forward(params)...); } } }; //------------------------------------------------------------------------------ // Description: // Implementation of the 2 array dispatch mechanism. template struct Dispatch2; //----------------------------// // First dispatch trampoline: // //----------------------------// template struct Dispatch2Trampoline; // Dispatch2 Terminal case: template struct Dispatch2 { template static bool Execute(T&&...) { #ifdef VTK_WARN_ON_DISPATCH_FAILURE vtkGenericWarningMacro("Dual array dispatch failed."); #endif return false; } }; // Dispatch2 Recursive case: template struct Dispatch2, ArrayList2> { typedef Dispatch2 NextDispatch; typedef Dispatch2Trampoline Trampoline; template static bool Execute( vtkDataArray* array1, vtkDataArray* array2, Worker&& worker, Params&&... params) { if (Array1Head* array = vtkArrayDownCast(array1)) { return Trampoline::Execute( array, array2, std::forward(worker), std::forward(params)...); } else { return NextDispatch::Execute( array1, array2, std::forward(worker), std::forward(params)...); } } }; // Dispatch2 Trampoline terminal case: template struct Dispatch2Trampoline { template static bool Execute(T&&...) { #ifdef VTK_WARN_ON_DISPATCH_FAILURE vtkGenericWarningMacro("Dual array dispatch failed."); #endif return false; } }; // Dispatch2 Trampoline recursive case: template struct Dispatch2Trampoline > { typedef Dispatch2Trampoline NextDispatch; template static bool Execute(Array1T* array1, vtkDataArray* array2, Worker&& worker, Params&&... params) { if (Array2Head* array = vtkArrayDownCast(array2)) { worker(array1, array, std::forward(params)...); return true; } else { return NextDispatch::Execute( array1, array2, std::forward(worker), std::forward(params)...); } } }; //------------------------------------------------------------------------------ // Description: // Implementation of the 2 array same-type dispatch mechanism. template struct Dispatch2Same; // Terminal case: template struct Dispatch2Same { template static bool Execute(T&&...) { #ifdef VTK_WARN_ON_DISPATCH_FAILURE vtkGenericWarningMacro("Dual array dispatch failed."); #endif return false; } }; // Recursive case: template struct Dispatch2Same, ArrayList2> { typedef Dispatch2Same NextDispatch; typedef vtkTypeList::Create ValueType; typedef typename FilterArraysByValueType::Result ValueArrayList; typedef Dispatch2Trampoline Trampoline; template static bool Execute( vtkDataArray* array1, vtkDataArray* array2, Worker&& worker, Params&&... params) { if (ArrayHead* array = vtkArrayDownCast(array1)) { return Trampoline::Execute( array, array2, std::forward(worker), std::forward(params)...); } else { return NextDispatch::Execute( array1, array2, std::forward(worker), std::forward(params)...); } } }; //------------------------------------------------------------------------------ // Description: // Implementation of the 3 array dispatch mechanism. template struct Dispatch3; //-----------------------------// // First dispatch trampoline: // //---------------------------// template struct Dispatch3Trampoline1; //------------------------------// // Second dispatch trampoline: // //----------------------------// template struct Dispatch3Trampoline2; // Dispatch3 Terminal case: template struct Dispatch3 { template static bool Execute(T&&...) { #ifdef VTK_WARN_ON_DISPATCH_FAILURE vtkGenericWarningMacro("Triple array dispatch failed."); #endif return false; } }; // Dispatch3 Recursive case: template struct Dispatch3, ArrayList2, ArrayList3> { private: typedef Dispatch3Trampoline1 Trampoline; typedef Dispatch3 NextDispatch; public: template static bool Execute(vtkDataArray* array1, vtkDataArray* array2, vtkDataArray* array3, Worker&& worker, Params&&... params) { if (ArrayHead* array = vtkArrayDownCast(array1)) { return Trampoline::Execute( array, array2, array3, std::forward(worker), std::forward(params)...); } else { return NextDispatch::Execute( array1, array2, array3, std::forward(worker), std::forward(params)...); } } }; // Dispatch3 Trampoline1 terminal case: template struct Dispatch3Trampoline1 { template static bool Execute(T&&...) { #ifdef VTK_WARN_ON_DISPATCH_FAILURE vtkGenericWarningMacro("Triple array dispatch failed."); #endif return false; } }; // Dispatch3 Trampoline1 recursive case: template struct Dispatch3Trampoline1, ArrayList3> { private: typedef Dispatch3Trampoline2 Trampoline; typedef Dispatch3Trampoline1 NextDispatch; public: template static bool Execute(Array1T* array1, vtkDataArray* array2, vtkDataArray* array3, Worker&& worker, Params&&... params) { if (ArrayHead* array = vtkArrayDownCast(array2)) { return Trampoline::Execute( array1, array, array3, std::forward(worker), std::forward(params)...); } else { return NextDispatch::Execute( array1, array2, array3, std::forward(worker), std::forward(params)...); } } }; // Dispatch3 Trampoline2 terminal case: template struct Dispatch3Trampoline2 { template static bool Execute(T&&...) { #ifdef VTK_WARN_ON_DISPATCH_FAILURE vtkGenericWarningMacro("Triple array dispatch failed."); #endif return false; } }; // Dispatch3 Trampoline2 recursive case: template struct Dispatch3Trampoline2 > { private: typedef Dispatch3Trampoline2 NextDispatch; public: template static bool Execute( Array1T* array1, Array2T* array2, vtkDataArray* array3, Worker&& worker, Params&&... params) { if (ArrayHead* array = vtkArrayDownCast(array3)) { worker(array1, array2, array, std::forward(params)...); return true; } else { return NextDispatch::Execute( array1, array2, array3, std::forward(worker), std::forward(params)...); } } }; //------------------------------------------------------------------------------ // Description: // Dispatch three arrays, enforcing that all three have the same ValueType. // Initially, set both ArraysToTest and ArrayList to the same TypeList. // ArraysToTest is iterated through, while ArrayList is preserved for later // dispatches. template struct Dispatch3Same; // Dispatch3Same terminal case: template struct Dispatch3Same { template static bool Execute(T&&...) { #ifdef VTK_WARN_ON_DISPATCH_FAILURE vtkGenericWarningMacro("Triple array dispatch failed."); #endif return false; } }; // Dispatch3Same recursive case: template struct Dispatch3Same, ArrayList2, ArrayList3> { private: typedef vtkTypeList::Create ValueType; typedef typename FilterArraysByValueType::Result ValueArrays2; typedef typename FilterArraysByValueType::Result ValueArrays3; typedef Dispatch3Trampoline1 Trampoline; typedef Dispatch3Same NextDispatch; public: template static bool Execute(vtkDataArray* array1, vtkDataArray* array2, vtkDataArray* array3, Worker&& worker, Params&&... params) { if (ArrayHead* array = vtkArrayDownCast(array1)) { return Trampoline::Execute( array, array2, array3, std::forward(worker), std::forward(params)...); } else { return NextDispatch::Execute( array1, array2, array3, std::forward(worker), std::forward(params)...); } } }; } // end namespace impl //------------------------------------------------------------------------------ // FilterArraysByValueType implementation: //------------------------------------------------------------------------------ // Terminal case: template struct FilterArraysByValueType { typedef vtkTypeList::NullType Result; }; // Recursive case: template struct FilterArraysByValueType, ValueList> { private: typedef typename ArrayHead::ValueType ValueType; enum { ValueIsAllowed = vtkTypeList::IndexOf::Result >= 0 }; typedef typename FilterArraysByValueType::Result NewTail; public: typedef typename vtkTypeList::Select, NewTail>::Result Result; }; //------------------------------------------------------------------------------ // DispatchByArray implementation: //------------------------------------------------------------------------------ // Preprocess and pass off to impl::Dispatch: template struct DispatchByArray > { private: typedef vtkTypeList::TypeList ArrayList; typedef typename vtkTypeList::Unique::Result UniqueArrays; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArrays; typedef impl::Dispatch ArrayDispatcher; public: template static bool Execute(vtkDataArray* inArray, Worker&& worker, Params&&... params) { return ArrayDispatcher::Execute( inArray, std::forward(worker), std::forward(params)...); } }; //------------------------------------------------------------------------------ // Dispatch implementation: // (defined after DispatchByArray to prevent 'incomplete type' errors) //------------------------------------------------------------------------------ struct Dispatch { private: typedef DispatchByArray Dispatcher; public: template static bool Execute(vtkDataArray* array, Worker&& worker, Params&&... params) { return Dispatcher::Execute( array, std::forward(worker), std::forward(params)...); } }; //------------------------------------------------------------------------------ // DispatchByValueType implementation: //------------------------------------------------------------------------------ // Preprocess and pass off to impl::Dispatch template struct DispatchByValueType > { private: typedef vtkTypeList::TypeList ValueTypeList; typedef typename FilterArraysByValueType::Result ArrayList; typedef typename vtkTypeList::Unique::Result UniqueArrays; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArrays; typedef impl::Dispatch ArrayDispatcher; public: template static bool Execute(vtkDataArray* inArray, Worker&& worker, Params&&... params) { return ArrayDispatcher::Execute( inArray, std::forward(worker), std::forward(params)...); } }; //------------------------------------------------------------------------------ // Dispatch2ByArray implementation: //------------------------------------------------------------------------------ // Preprocess and pass off to impl::Dispatch2: template struct Dispatch2ByArray { private: typedef typename vtkTypeList::Unique::Result UniqueArray1; typedef typename vtkTypeList::Unique::Result UniqueArray2; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArray1; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArray2; typedef impl::Dispatch2 ArrayDispatcher; public: template static bool Execute( vtkDataArray* array1, vtkDataArray* array2, Worker&& worker, Params&&... params) { return ArrayDispatcher::Execute( array1, array2, std::forward(worker), std::forward(params)...); } }; //------------------------------------------------------------------------------ // Dispatch2 implementation: //------------------------------------------------------------------------------ struct Dispatch2 { private: typedef Dispatch2ByArray Dispatcher; public: template static bool Execute( vtkDataArray* array1, vtkDataArray* array2, Worker&& worker, Params&&... params) { return Dispatcher::Execute( array1, array2, std::forward(worker), std::forward(params)...); } }; //------------------------------------------------------------------------------ // Dispatch2ByValueType implementation: //------------------------------------------------------------------------------ // Preprocess and pass off to impl::Dispatch2 template struct Dispatch2ByValueType { private: typedef typename FilterArraysByValueType::Result ArrayList1; typedef typename FilterArraysByValueType::Result ArrayList2; typedef typename vtkTypeList::Unique::Result UniqueArray1; typedef typename vtkTypeList::Unique::Result UniqueArray2; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArray1; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArray2; typedef impl::Dispatch2 ArrayDispatcher; public: template static bool Execute( vtkDataArray* array1, vtkDataArray* array2, Worker&& worker, Params&&... params) { return ArrayDispatcher::Execute( array1, array2, std::forward(worker), std::forward(params)...); } }; //------------------------------------------------------------------------------ // Dispatch2BySameValueType implementation: //------------------------------------------------------------------------------ // Preprocess and pass off to impl::Dispatch2Same template struct Dispatch2BySameValueType { private: typedef typename FilterArraysByValueType::Result ArrayList; typedef typename vtkTypeList::Unique::Result UniqueArray; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArray; typedef impl::Dispatch2Same Dispatcher; public: template static bool Execute( vtkDataArray* array1, vtkDataArray* array2, Worker&& worker, Params&&... params) { return Dispatcher::Execute( array1, array2, std::forward(worker), std::forward(params)...); } }; //------------------------------------------------------------------------------ // Dispatch2ByArrayWithSameValueType implementation: //------------------------------------------------------------------------------ // Preprocess and pass off to impl::Dispatch2Same template struct Dispatch2ByArrayWithSameValueType { private: typedef typename vtkTypeList::Unique::Result UniqueArray1; typedef typename vtkTypeList::Unique::Result UniqueArray2; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArray1; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArray2; typedef impl::Dispatch2Same Dispatcher; public: template static bool Execute( vtkDataArray* array1, vtkDataArray* array2, Worker&& worker, Params&&... params) { return Dispatcher::Execute( array1, array2, std::forward(worker), std::forward(params)...); } }; //------------------------------------------------------------------------------ // Dispatch2SameValueType implementation: //------------------------------------------------------------------------------ struct Dispatch2SameValueType { private: typedef Dispatch2ByArrayWithSameValueType Dispatcher; public: template static bool Execute( vtkDataArray* array1, vtkDataArray* array2, Worker&& worker, Params&&... params) { return Dispatcher::Execute( array1, array2, std::forward(worker), std::forward(params)...); } }; //------------------------------------------------------------------------------ // Dispatch3ByArray implementation: //------------------------------------------------------------------------------ // Preprocess and pass off to impl::Dispatch3: template struct Dispatch3ByArray { private: typedef typename vtkTypeList::Unique::Result UniqueArray1; typedef typename vtkTypeList::Unique::Result UniqueArray2; typedef typename vtkTypeList::Unique::Result UniqueArray3; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArray1; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArray2; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArray3; typedef impl::Dispatch3 ArrayDispatcher; public: template static bool Execute(vtkDataArray* array1, vtkDataArray* array2, vtkDataArray* array3, Worker&& worker, Params&&... params) { return ArrayDispatcher::Execute( array1, array2, array3, std::forward(worker), std::forward(params)...); } }; //------------------------------------------------------------------------------ // Dispatch3 implementation: //------------------------------------------------------------------------------ struct Dispatch3 { private: typedef Dispatch3ByArray Dispatcher; public: template static bool Execute(vtkDataArray* array1, vtkDataArray* array2, vtkDataArray* array3, Worker&& worker, Params&&... params) { return Dispatcher::Execute( array1, array2, array3, std::forward(worker), std::forward(params)...); } }; //------------------------------------------------------------------------------ // Dispatch3ByValueType implementation: //------------------------------------------------------------------------------ // Preprocess and pass off to impl::Dispatch3 template struct Dispatch3ByValueType { private: typedef typename FilterArraysByValueType::Result ArrayList1; typedef typename FilterArraysByValueType::Result ArrayList2; typedef typename FilterArraysByValueType::Result ArrayList3; typedef typename vtkTypeList::Unique::Result UniqueArray1; typedef typename vtkTypeList::Unique::Result UniqueArray2; typedef typename vtkTypeList::Unique::Result UniqueArray3; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArray1; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArray2; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArray3; typedef impl::Dispatch3 ArrayDispatcher; public: template static bool Execute(vtkDataArray* array1, vtkDataArray* array2, vtkDataArray* array3, Worker&& worker, Params&&... params) { return ArrayDispatcher::Execute( array1, array2, array3, std::forward(worker), std::forward(params)...); } }; //------------------------------------------------------------------------------ // Dispatch3BySameValueType implementation: //------------------------------------------------------------------------------ // Preprocess and pass off to impl::Dispatch3Same template struct Dispatch3BySameValueType { private: typedef typename FilterArraysByValueType::Result ArrayList; typedef typename vtkTypeList::Unique::Result UniqueArray; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArray; typedef impl::Dispatch3Same Dispatcher; public: template static bool Execute(vtkDataArray* array1, vtkDataArray* array2, vtkDataArray* array3, Worker&& worker, Params&&... params) { return Dispatcher::Execute( array1, array2, array3, std::forward(worker), std::forward(params)...); } }; //------------------------------------------------------------------------------ // Dispatch3BySameValueType implementation: //------------------------------------------------------------------------------ // Preprocess and pass off to impl::Dispatch3Same template struct Dispatch3ByArrayWithSameValueType { private: typedef typename vtkTypeList::Unique::Result UniqueArray1; typedef typename vtkTypeList::Unique::Result UniqueArray2; typedef typename vtkTypeList::Unique::Result UniqueArray3; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArray1; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArray2; typedef typename vtkTypeList::DerivedToFront::Result SortedUniqueArray3; typedef impl::Dispatch3Same Dispatcher; public: template static bool Execute(vtkDataArray* array1, vtkDataArray* array2, vtkDataArray* array3, Worker&& worker, Params&&... params) { return Dispatcher::Execute( array1, array2, array3, std::forward(worker), std::forward(params)...); } }; //------------------------------------------------------------------------------ // Dispatch3SameValueType implementation: //------------------------------------------------------------------------------ struct Dispatch3SameValueType { private: typedef Dispatch3ByArrayWithSameValueType Dispatcher; public: template static bool Execute(vtkDataArray* array1, vtkDataArray* array2, vtkDataArray* array3, Worker&& worker, Params&&... params) { return Dispatcher::Execute( array1, array2, array3, std::forward(worker), std::forward(params)...); } }; } // end namespace vtkArrayDispatch #endif // vtkArrayDispatch_txx