diff --git a/vtkm/List.h b/vtkm/List.h index 1f2dd73bb..c98e34b54 100644 --- a/vtkm/List.h +++ b/vtkm/List.h @@ -128,6 +128,169 @@ using ListApply = typename detail::ListApplyImpl, Target> namespace detail { +template +struct ListAppendImpl; + +template <> +struct ListAppendImpl<> +{ + using type = vtkm::ListEmpty; +}; + +template +struct ListAppendImpl +{ + using type = L; +}; + +template +struct ListAppendImpl, vtkm::List> +{ + using type = vtkm::List; +}; + +template +struct ListAppendImpl, vtkm::List, vtkm::List> +{ + using type = vtkm::List; +}; + +template +struct ListAppendImpl, + vtkm::List, + vtkm::List, + vtkm::List> +{ + using type = vtkm::List; +}; + +template +struct ListAppendImpl, + vtkm::List, + vtkm::List, + vtkm::List, + vtkm::List> +{ + using type = vtkm::List; +}; + +template +struct ListAppendImpl, + vtkm::List, + vtkm::List, + vtkm::List, + vtkm::List, + vtkm::List> +{ + using type = vtkm::List; +}; + +template +struct ListAppendImpl, + vtkm::List, + vtkm::List, + vtkm::List, + vtkm::List, + vtkm::List, + vtkm::List> +{ + using type = vtkm::List; +}; + +template +struct ListAppendImpl, + vtkm::List, + vtkm::List, + vtkm::List, + vtkm::List, + vtkm::List, + vtkm::List, + vtkm::List> +{ + using type = vtkm::List; +}; + +template +struct ListAppendImpl, + vtkm::List, + vtkm::List, + vtkm::List, + vtkm::List, + vtkm::List, + vtkm::List, + vtkm::List, + Ls...> + : ListAppendImpl, + Ls...> +{ +}; + +} // namespace detail + +/// Concatinates a set of lists into a single list. +/// +/// Note that this does not work correctly with `vtkm::ListUniversal`. +template +using ListAppend = typename detail::ListAppendImpl...>::type; + +namespace detail +{ + +template +struct ListFillImpl +{ + using type = typename ListAppendImpl::type, + typename ListFillImpl::type>::type; +}; + +template +struct ListFillImpl +{ + using type = vtkm::List; +}; + +template +struct ListFillImpl +{ + using type = vtkm::List<>; +}; + +} // namespace detail + +/// \brief Returns a list filled with N copies of type T +/// +template +using ListFill = typename detail::ListFillImpl::type; + +namespace detail +{ + template struct ListSizeImpl; @@ -148,84 +311,32 @@ using ListSize = typename detail::ListSizeImpl>::type; namespace detail { -template +template +struct ListAtImplFunc; + +template +struct ListAtImplFunc> +{ + // Rather than declare a `type`, make a declaration of a function that returns the type + // after some number of `const void*` arguments. We can use ListFill to quickly create + // the list of `const void*` arguments, so the type can be returned. We can then use + // decltype to get the returned type. + // + // Templating the `Other` should not be strictly necessary. (You should be able to just + // end with `...`.) But some compilers (such as CUDA 8 and Intel 18) have a problem with + // that. + template + static T at(VoidTypes..., T*, Other...); +}; + +template struct ListAtImpl; -template -struct ListAtImpl<0, true, vtkm::List> -{ - using type = Tx; -}; -template -struct ListAtImpl<1, true, vtkm::List> -{ - using type = Tx; -}; -template -struct ListAtImpl<2, true, vtkm::List> -{ - using type = Tx; -}; -template -struct ListAtImpl<3, true, vtkm::List> -{ - using type = Tx; -}; -template -struct ListAtImpl<4, true, vtkm::List> -{ - using type = Tx; -}; -template -struct ListAtImpl<5, true, vtkm::List> -{ - using type = Tx; -}; -template -struct ListAtImpl<6, true, vtkm::List> -{ - using type = Tx; -}; -template -struct ListAtImpl<7, true, vtkm::List> -{ - using type = Tx; -}; - -template -struct ListAtImpl> - : ListAtImpl> +template +struct ListAtImpl, Index> { + using type = + decltype(ListAtImplFunc>::at(static_cast(nullptr)...)); }; } // namespace detail @@ -235,7 +346,7 @@ struct ListAtImpl> /// This becomes the type of the list at the given index. /// template -using ListAt = typename detail::ListAtImpl>::type; +using ListAt = typename detail::ListAtImpl, Index>::type; namespace detail { @@ -467,140 +578,6 @@ using ListHas = typename detail::ListHasImpl, T>::type; namespace detail { -template -struct ListAppendImpl; - -template <> -struct ListAppendImpl<> -{ - using type = vtkm::ListEmpty; -}; - -template -struct ListAppendImpl -{ - using type = L; -}; - -template -struct ListAppendImpl, vtkm::List> -{ - using type = vtkm::List; -}; - -template -struct ListAppendImpl, vtkm::List, vtkm::List> -{ - using type = vtkm::List; -}; - -template -struct ListAppendImpl, - vtkm::List, - vtkm::List, - vtkm::List> -{ - using type = vtkm::List; -}; - -template -struct ListAppendImpl, - vtkm::List, - vtkm::List, - vtkm::List, - vtkm::List> -{ - using type = vtkm::List; -}; - -template -struct ListAppendImpl, - vtkm::List, - vtkm::List, - vtkm::List, - vtkm::List, - vtkm::List> -{ - using type = vtkm::List; -}; - -template -struct ListAppendImpl, - vtkm::List, - vtkm::List, - vtkm::List, - vtkm::List, - vtkm::List, - vtkm::List> -{ - using type = vtkm::List; -}; - -template -struct ListAppendImpl, - vtkm::List, - vtkm::List, - vtkm::List, - vtkm::List, - vtkm::List, - vtkm::List, - vtkm::List> -{ - using type = vtkm::List; -}; - -template -struct ListAppendImpl, - vtkm::List, - vtkm::List, - vtkm::List, - vtkm::List, - vtkm::List, - vtkm::List, - vtkm::List, - Ls...> - : ListAppendImpl, - Ls...> -{ -}; - -} // namespace detail - -/// Concatinates a set of lists into a single list. -/// -/// Note that this does not work correctly with `vtkm::ListUniversal`. -template -using ListAppend = typename detail::ListAppendImpl...>::type; - -namespace detail -{ - template class Target> struct ListTransformImpl; template class Target> diff --git a/vtkm/testing/UnitTestList.cxx b/vtkm/testing/UnitTestList.cxx index 5638ba95e..db9e0b1ec 100644 --- a/vtkm/testing/UnitTestList.cxx +++ b/vtkm/testing/UnitTestList.cxx @@ -178,6 +178,9 @@ void TestLists() vtkm::List>, vtkm::List, TestClass<22>>>{}); + std::cout << "ListFill" << std::endl; + CheckList(vtkm::List{}, vtkm::ListFill{}); + std::cout << "ListTransform" << std::endl; CheckList(EvenList{}, vtkm::ListTransform{});