From 9562de945747d17c37c0f63817d4519e3063a96b Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Thu, 10 Feb 2022 10:34:54 -0700 Subject: [PATCH] Remove brigand from DispatcherBase --- vtkm/worklet/internal/DispatcherBase.h | 147 +++++++++++++------------ 1 file changed, 77 insertions(+), 70 deletions(-) diff --git a/vtkm/worklet/internal/DispatcherBase.h b/vtkm/worklet/internal/DispatcherBase.h index ae85fe38a..c38fa00ed 100644 --- a/vtkm/worklet/internal/DispatcherBase.h +++ b/vtkm/worklet/internal/DispatcherBase.h @@ -10,6 +10,7 @@ #ifndef vtk_m_worklet_internal_DispatcherBase_h #define vtk_m_worklet_internal_DispatcherBase_h +#include #include #include @@ -26,12 +27,11 @@ #include -#include - #include #include +#include #include #include @@ -131,57 +131,63 @@ inline T&& as_ref(T&& t) template -struct ReportTypeOnError; -template -struct ReportTypeOnError : std::true_type +struct ReportTypeOnError : std::integral_constant { }; template -struct ReportValueOnError; -template -struct ReportValueOnError : std::true_type +struct ReportValueOnError : std::integral_constant { }; -// Is designed as a brigand fold operation. -template -struct DetermineIfHasDynamicParameter +template +struct IsDynamicTypeImpl { using T = vtkm::internal::remove_pointer_and_decay; using DynamicTag = typename vtkm::cont::internal::DynamicTransformTraits::DynamicTag; - using isDynamic = + using type = typename std::is_same::type; - - using type = std::integral_constant; }; +template +using IsDynamicType = typename IsDynamicTypeImpl::type; - -// Is designed as a brigand fold operation. -template -struct DetermineHasCorrectParameters +template +struct ZipControlParamImpl; +template +struct ZipControlParamImpl, + vtkm::List, + vtkmstd::integer_sequence> { - template - struct Functor - { - //T is the type of the Param at the current index - //State if the index to use to fetch the control signature tag - using ControlSignatureTag = typename brigand::at_c; - using TypeCheckTag = typename ControlSignatureTag::TypeCheckTag; + VTKM_STATIC_ASSERT(sizeof...(SigTags) == sizeof...(Params)); + VTKM_STATIC_ASSERT(sizeof...(SigTags) == sizeof...(Indices)); - using T = typename std::remove_pointer::type; + using type = vtkm::List< + vtkm::List>...>; +}; +template +using ZipControlParam = typename ZipControlParamImpl::type; + +template +struct ControlArgumentValidator +{ + template + void operator()(vtkm::List>) const + { + using T = std::remove_pointer_t; + using TypeCheckTag = typename SigTag::TypeCheckTag; static constexpr bool isCorrect = vtkm::cont::arg::TypeCheck::value; - // If you get an error on the line below, that means that your code has called the - // Invoke method on a dispatcher, and one of the arguments of the Invoke is the wrong - // type. Each argument of Invoke corresponds to a tag in the arguments of the - // ControlSignature of the worklet. If there is a mismatch, then you get an error here - // (instead of where you called the dispatcher). For example, if the worklet has a - // control signature as ControlSignature(CellSetIn, ...) and the first argument passed - // to Invoke is an ArrayHandle, you will get an error here because you cannot use an - // ArrayHandle in place of a CellSetIn argument. (You need to use a CellSet.) See a few - // lines later for some diagnostics to help you trace where the error occurred. - VTKM_READ_THE_SOURCE_CODE_FOR_HELP(isCorrect); + static_assert( + isCorrect, + "If you get an error here, that means that your code has invoked a worklet," + " and one of the arguments of the Invoke is the wrong type. Each argument of the invoke" + " corresponds to a tag in the arguments of the ControlSignature of the worklet. If there" + " is a mismatch, then you get an error here (instead of where you called invoke). For" + " example, if the worklet has a control signature as ControlSignature(CellSetIn, ...) and" + " the first argument passed to the invoke is an ArrayHandle, you will get an error here" + " because you cannot use an ArrayHandle in place of a CellSetIn argument. (You need to use" + " a CellSet.) If the compiler supports it, the next few errors on the following lines of" + " code will give information about where the error actually occurred."); // If you are getting the error described above, the following lines will give you some // diagnostics (in the form of compile errors). Each one will result in a compile error @@ -191,20 +197,16 @@ struct DetermineHasCorrectParameters // type/value being reported. (Note that some compilers report better types than others. If // your compiler is giving unhelpful types like "T" or "WorkletType", you may need to try a // different compiler.) - static_assert(ReportTypeOnError::value, "Type passed to Invoke"); - static_assert(ReportTypeOnError::value, "Worklet being invoked."); - static_assert(ReportValueOnError::value, "Index of Invoke parameter"); - static_assert(ReportTypeOnError::value, "Type check tag used"); - - // This final static_assert gives a human-readable error message. Ideally, this would be - // placed first, but some compilers will suppress further errors when a static_assert - // fails, so you would not see the other diagnostic error messages. - static_assert(isCorrect, - "The type of one of the arguments to the dispatcher's Invoke method is " - "incompatible with the corresponding tag in the worklet's ControlSignature."); - - using type = std::integral_constant; - }; + static_assert(ReportTypeOnError::value, + "The first template argument to ReportTypeOnError is the worklet being invoked"); + static_assert(ReportValueOnError::value, + "The first template argument to ReportTypeOnError is the index of Invoke " + "parameter (starting at index 1)"); + static_assert(ReportTypeOnError::value, + "The first template argument to ReportTypeOnError is the type passed to Invoke"); + static_assert(ReportTypeOnError::value, + "The first template argument to ReportTypeOnError is the type check tag used"); + } }; // Checks that an argument in a ControlSignature is a valid control signature @@ -341,6 +343,18 @@ private: void operator=(const DispatcherBaseTransportFunctor&) = delete; }; +// Should this functionality be added to List.h? Should there be the general ability to +// remove some number of items from the beginning or end of a list? +template +struct ListRemoveFirstImpl; +template +struct ListRemoveFirstImpl> +{ + using type = vtkm::List; +}; +template +using ListRemoveFirst = typename ListRemoveFirstImpl::type; + //forward declares template struct for_each_dynamic_arg; @@ -379,7 +393,7 @@ inline void convert_arg(vtkm::cont::internal::DynamicTransformTagStatic, const Trampoline& trampoline, Args&&... args) { //This is a static array, so just push it to the back - using popped_sig = brigand::pop_front; + using popped_sig = ListRemoveFirst; for_each_dynamic_arg()( trampoline, popped_sig(), std::forward(args)..., std::forward(t)); } @@ -395,8 +409,8 @@ inline void convert_arg(vtkm::cont::internal::DynamicTransformTagCastAndCall, const Trampoline& trampoline, Args&&... args) { //This is something dynamic so cast and call - using tag_check = typename brigand::at_c::TypeCheckTag; - using popped_sig = brigand::pop_front; + using tag_check = typename vtkm::ListAt::TypeCheckTag; + using popped_sig = ListRemoveFirst; not_nullptr(t, LeftToProcess, 1); vtkm::cont::CastAndCall(as_ref(t), @@ -448,7 +462,7 @@ struct PlaceholderValidator // An overload operator to detect possible out of bound placeholder template - void operator()(brigand::type_>) const + void operator()(vtkm::internal::meta::Type>) const { static_assert(N <= MaxIndexAllowed, "An argument in the execution signature" @@ -459,7 +473,7 @@ struct PlaceholderValidator } template - void operator()(brigand::type_) const + void operator()(vtkm::internal::meta::Type) const { } }; @@ -511,7 +525,8 @@ private: // Check if the placeholders defined in the execution environment exceed the max bound // defined in the control environment by throwing a nice compile error. using ComponentSig = typename ExecutionInterface::ComponentSig; - brigand::for_each(PlaceholderValidator{}); + vtkm::ListForEach(PlaceholderValidator{}, + vtkm::ListTransform{}); //We need to determine if we have the need to do any dynamic //transforms. This is fairly simple of a query. We just need to check @@ -520,10 +535,7 @@ private: //check & convert code when we already know all the types. This results //in smaller executables and libraries. using ParamTypes = typename ParameterInterface::ParameterSig; - using HasDynamicTypes = - brigand::fold>; + using HasDynamicTypes = vtkm::ListAny>; this->StartInvokeDynamic(HasDynamicTypes(), std::forward(args)...); } @@ -553,18 +565,13 @@ private: using ParamTypes = typename ParameterInterface::ParameterSig; using ContSigTypes = typename vtkm::internal::detail::FunctionSigInfo< typename WorkletType::ControlSignature>::Parameters; - - //isAllValid will throw a compile error if everything doesn't match - using isAllValid = brigand::fold< + using ParamZip = detail::ZipControlParam< + ContSigTypes, ParamTypes, - std::integral_constant, - typename detail::DetermineHasCorrectParameters:: - template Functor>>; + vtkmstd::make_integer_sequence::value>>; - //this warning exists so that we don't get a warning from not using isAllValid - using expectedLen = std::integral_constant; - static_assert(isAllValid::value == expectedLen::value, - "All arguments failed the TypeCheck pass"); + // This will cause compile errors if there is an argument mismatch. + vtkm::ListForEach(detail::ControlArgumentValidator{}, ParamZip{}); auto fi = vtkm::internal::make_FunctionInterface...>(args...);