Enable predicate parameter to ListAll and ListAny

In pretty much any practical circumstance, whenusing `ListAll` or
`ListAny`, you have a list of types on which you run some sort of
predicate on each item in the list to determine whether any or all of
the items match the predicate. To make this easier, add a second
argument to `ListAll` and `ListAny` to provide a predicate that will
automatically be added.

If no predicate is given, then the operation is run directly on the
list. This is implemented by just using an identity operation.
This commit is contained in:
Kenneth Moreland 2022-03-08 09:24:38 -07:00
parent 0f96a6b0be
commit 2b64630674
6 changed files with 53 additions and 11 deletions

@ -871,18 +871,48 @@ using ListReduce = typename detail::ListReduceImpl<internal::AsList<List>, Opera
/// (such as `std::true_type` and `std::false_type`. Resolves to `std::true_type` if all the types
/// are true, `std::false_type` otherwise. If the list is empty, resolves to `std::true_type`.
///
template <typename List>
using ListAll = vtkm::ListReduce<List, vtkm::internal::meta::And, std::true_type>;
/// `ListAll` also accepts an optional second argument that is a template that is a predicate
/// applied to each item in the input list before checking for the `value` type.
///
/// ```cpp
/// using NumberList1 = vtkm::List<int, char>;
/// using NumberList2 = vtkm::List<int, float>;
///
/// // Resolves to std::true_type
/// using AllInt1 = vtkm::ListAll<NumberList1, std::is_integral>;
///
/// // Resolves to std::false_type (because float is not integral)
/// using AllInt2 = vtkm::ListAll<NumberList2, std::is_integral>;
/// ```
///
template <typename List, template <typename> class Predicate = vtkm::internal::meta::Identity>
using ListAll =
vtkm::ListReduce<vtkm::ListTransform<List, Predicate>, vtkm::internal::meta::And, std::true_type>;
/// \brief Determines whether any of the types in the list are "true."
///
/// `ListAll` expects a `vtkm::List` with types that have a `value` that is either true or false
/// `ListAny` expects a `vtkm::List` with types that have a `value` that is either true or false
/// (such as `std::true_type` and `std::false_type`. Resolves to `std::true_type` if any of the
/// types are true, `std::false_type` otherwise. If the list is empty, resolves to
/// `std::false_type`.
///
template <typename List>
using ListAny = vtkm::ListReduce<List, vtkm::internal::meta::Or, std::false_type>;
/// `ListAny` also accepts an optional second argument that is a template that is a predicate
/// applied to each item in the input list before checking for the `value` type.
///
/// ```cpp
/// using NumberList1 = vtkm::List<int, float>;
/// using NumberList2 = vtkm::List<float, double>;
///
/// // Resolves to std::true_type
/// using AnyInt1 = vtkm::ListAny<NumberList1, std::is_integral>;
///
/// // Resolves to std::false_type
/// using AnyInt2 = vtkm::ListAny<NumberList2, std::is_integral>;
/// ```
///
template <typename List, template <typename> class Predicate = vtkm::internal::meta::Identity>
using ListAny =
vtkm::ListReduce<vtkm::ListTransform<List, Predicate>, vtkm::internal::meta::Or, std::false_type>;
#undef VTKM_CHECK_LIST_SIZE

@ -32,7 +32,7 @@ namespace compvec
template <typename... PortalList>
using AllPortalsAreWritable =
vtkm::ListAll<vtkm::List<vtkm::internal::PortalSupportsSets<PortalList>...>>;
vtkm::ListAll<vtkm::List<PortalList...>, vtkm::internal::PortalSupportsSets>;
// GetValueType: ---------------------------------------------------------------
// Determines the output `ValueType` of the set of `ArrayHandle` objects. For example, if the input

@ -109,8 +109,7 @@ namespace decor
// Ensures that all types in variadic container ArrayHandleList are subclasses
// of ArrayHandleBase.
template <typename ArrayHandleList>
using AllAreArrayHandles =
vtkm::ListAll<vtkm::ListTransform<ArrayHandleList, vtkm::cont::internal::ArrayHandleCheck>>;
using AllAreArrayHandles = vtkm::ListAll<ArrayHandleList, vtkm::cont::internal::ArrayHandleCheck>;
namespace detail
{
@ -249,8 +248,7 @@ GetReadPortalType<typename std::decay<ArrayT>::type> ReadPortal(const ArrayT& ar
// Equivalent to std::true_type if *any* portal in PortalList can be written to.
// If all are read-only, std::false_type is used instead.
template <typename PortalList>
using AnyPortalIsWritable =
vtkm::ListAny<vtkm::ListTransform<PortalList, vtkm::internal::PortalSupportsSets>>;
using AnyPortalIsWritable = vtkm::ListAny<PortalList, vtkm::internal::PortalSupportsSets>;
// Set to std::true_type if DecoratorImplT::CreateInverseFunctor can be called
// with the supplied portals, or std::false_type otherwise.

@ -66,6 +66,11 @@ using Or = typename detail::OrImpl<T1, T2>::type;
template <typename T>
using Not = typename detail::NotImpl<T>::type;
/// A single argument template that becomes its argument. Useful for passing an identity to
/// transformations.
template <typename T>
using Identity = T;
}
}
} // namespace vtkm::internal::meta

@ -297,6 +297,10 @@ void TestLists()
VTKM_TEST_ASSERT((vtkm::ListAll<vtkm::ListTransform<EvenList, EvenPredicate>>::value == true));
VTKM_TEST_ASSERT((vtkm::ListAll<vtkm::ListTransform<LongList, EvenPredicate>>::value == false));
VTKM_TEST_ASSERT((vtkm::ListAll<vtkm::List<>>::value == true));
VTKM_TEST_ASSERT((vtkm::ListAll<SimpleCount, EvenPredicate>::value == false));
VTKM_TEST_ASSERT((vtkm::ListAll<EvenList, EvenPredicate>::value == true));
VTKM_TEST_ASSERT((vtkm::ListAll<LongList, EvenPredicate>::value == false));
VTKM_TEST_ASSERT((vtkm::ListAll<vtkm::List<>, EvenPredicate>::value == true));
std::cout << "ListAny" << std::endl;
VTKM_TEST_ASSERT((vtkm::ListAny<vtkm::ListTransform<SimpleCount, EvenPredicate>>::value == true));
@ -304,6 +308,11 @@ void TestLists()
VTKM_TEST_ASSERT((vtkm::ListAny<vtkm::ListTransform<EvenList, OddPredicate>>::value == false));
VTKM_TEST_ASSERT((vtkm::ListAny<vtkm::ListTransform<LongList, EvenPredicate>>::value == true));
VTKM_TEST_ASSERT((vtkm::ListAny<vtkm::List<>>::value == false));
VTKM_TEST_ASSERT((vtkm::ListAny<SimpleCount, EvenPredicate>::value == true));
VTKM_TEST_ASSERT((vtkm::ListAny<EvenList, EvenPredicate>::value == true));
VTKM_TEST_ASSERT((vtkm::ListAny<EvenList, OddPredicate>::value == false));
VTKM_TEST_ASSERT((vtkm::ListAny<LongList, EvenPredicate>::value == true));
VTKM_TEST_ASSERT((vtkm::ListAny<vtkm::List<>, EvenPredicate>::value == false));
}
} // anonymous namespace

@ -535,7 +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 = vtkm::ListAny<vtkm::ListTransform<ParamTypes, detail::IsDynamicType>>;
using HasDynamicTypes = vtkm::ListAny<ParamTypes, detail::IsDynamicType>;
this->StartInvokeDynamic(HasDynamicTypes(), std::forward<Args>(args)...);
}