Introduces ListTagUniversal which represents a list of everything.

This makes the FilterTraits design simpler and easier to understand.
This commit is contained in:
Robert Maynard 2016-12-30 15:42:18 -05:00
parent 9eb288419e
commit c27bb01f26
4 changed files with 98 additions and 12 deletions

@ -51,6 +51,13 @@ struct ListTagCheck : std::is_base_of<vtkm::detail::ListRoot,ListTag>
"Provided type is not a valid VTK-m list tag.")
/// A special tag for a list that represents holding all potential values
///
/// Note: Can not be used with ForEach for obvious reasons.
struct ListTagUniversal : detail::ListRoot {
using list = vtkm::detail::ListBase<vtkm::detail::UniversalTag>;
};
/// A special tag for an empty list.
///
struct ListTagEmpty : detail::ListRoot {
@ -61,7 +68,9 @@ struct ListTagEmpty : detail::ListRoot {
/// can be subclassed and still behave like a list tag.
template<typename ListTag1, typename ListTag2>
struct ListTagJoin : detail::ListRoot {
using list = typename detail::ListJoin<ListTag1,ListTag2>::type;
using list = typename detail::ListJoin<
typename ListTag1::list,
typename ListTag2::list>::type;
};
/// A tag that consits of elements that are found in both tags. This struct

@ -30,9 +30,9 @@ class FilterTraits
{
public:
// A filter is able to state what subset of types it supports
// by default. By default we use the empty tag to represent that the
// by default. By default we use ListTagUniversal to represent that the
// filter accepts all types specified by the users provided policy
typedef vtkm::ListTagEmpty InputFieldTypeList;
typedef vtkm::ListTagUniversal InputFieldTypeList;
};
template<typename DerivedPolicy, typename FilterType>
@ -41,11 +41,7 @@ struct DeduceFilterFieldTypes
using FList = typename vtkm::filter::FilterTraits<FilterType>::InputFieldTypeList;
using PList = typename DerivedPolicy::FieldTypeList;
using FListIsEmpty = std::is_same<vtkm::ListTagEmpty,FList>;
using TypeList = typename std::conditional<FListIsEmpty::value,
PList, //filter list is empty
vtkm::ListTagIntersect<FList, PList>
>::type;
using TypeList = vtkm::ListTagIntersect<FList, PList>;
};
}

@ -41,11 +41,32 @@ struct ListRoot { };
template <class... T>
using ListBase = brigand::list<T...>;
/// list value that is used to represent a list actually matches all values
struct UniversalTag
{
//We never want this tag constructed, and by deleting the constructor
//we get an error when trying to use this class with ForEach.
UniversalTag()=delete;
};
//-----------------------------------------------------------------------------
template<typename ListTag1, typename ListTag2>
struct ListJoin
{
using type = brigand::append< typename ListTag1::list, typename ListTag2::list>;
using type = brigand::append<ListTag1,ListTag2>;
};
template<typename ListTag>
struct ListJoin<vtkm::detail::ListBase<vtkm::detail::UniversalTag>, ListTag>
{
using type = vtkm::detail::ListBase<vtkm::detail::UniversalTag>;
};
template<typename ListTag>
struct ListJoin<ListTag, vtkm::detail::ListBase<vtkm::detail::UniversalTag> >
{
using type = vtkm::detail::ListBase<vtkm::detail::UniversalTag>;
};
//-----------------------------------------------------------------------------
@ -58,6 +79,13 @@ struct ListContainsImpl<Type, brigand::empty_sequence >
static VTKM_CONSTEXPR bool value = false;
};
//-----------------------------------------------------------------------------
template<typename Type>
struct ListContainsImpl<Type, brigand::list<vtkm::detail::UniversalTag> >
{
static VTKM_CONSTEXPR bool value = true;
};
//-----------------------------------------------------------------------------
template<typename Type,
typename T1>
@ -133,6 +161,18 @@ struct ListIntersect
>;
};
template<typename ListTag>
struct ListIntersect<vtkm::detail::ListBase<vtkm::detail::UniversalTag>, ListTag>
{
using type = ListTag;
};
template<typename ListTag>
struct ListIntersect<ListTag, vtkm::detail::ListBase<vtkm::detail::UniversalTag> >
{
using type = ListTag;
};
template<typename SameListTag>
struct ListIntersect<SameListTag, SameListTag>
{

@ -59,6 +59,10 @@ struct TestListTagIntersect
: vtkm::ListTagIntersect<TestListTag3, TestListTagJoin>
{ };
struct TestListTagUniversal
: vtkm::ListTagUniversal
{ };
struct MutableFunctor
{
std::vector<int> FoundTypes;
@ -101,10 +105,9 @@ void CheckSame(const vtkm::Vec<int,N> &expected,
}
template<int N, typename ListTag>
void CheckContains(TestClass<N>, ListTag, const std::vector<int> contents)
void CheckContains(TestClass<N>, ListTag, const std::vector<int>& contents)
{
//First use intersect to verify at compile time that ListTag contains
//TestClass<N>
//Use intersect to verify at compile time that ListTag contains TestClass<N>
using intersectWith = vtkm::ListTagBase< TestClass<N> >;
using intersectResult = typename vtkm::ListTagIntersect<intersectWith, ListTag>::list;
VTKM_CONSTEXPR bool intersectContains = (brigand::size<intersectResult>::value != 0);
@ -119,6 +122,20 @@ void CheckContains(TestClass<N>, ListTag, const std::vector<int> contents)
"ListContains check failed.");
}
template<int N>
void CheckContains(TestClass<N>, TestListTagUniversal, const std::vector<int>&)
{
//Use intersect to verify at compile time that ListTag contains TestClass<N>
using intersectWith = vtkm::ListTagBase< TestClass<N> >;
using intersectResult = typename vtkm::ListTagIntersect<intersectWith, TestListTagUniversal>::list;
VTKM_CONSTEXPR bool intersectContains = (brigand::size<intersectResult>::value != 0);
VTKM_CONSTEXPR bool listContains = vtkm::ListContains<TestListTagUniversal, TestClass<N> >::value;
VTKM_TEST_ASSERT(intersectContains == listContains,
"ListTagIntersect check failed.");
}
template<vtkm::IdComponent N, typename ListTag>
void TryList(const vtkm::Vec<int,N> &expected, ListTag)
{
@ -146,6 +163,27 @@ void TryList(const vtkm::Vec<int,N> &expected, ListTag)
CheckContains(TestClass<44>(), ListTag(), functor.FoundTypes);
}
template<vtkm::IdComponent N>
void TryList(const vtkm::Vec<int,N> &expected, TestListTagUniversal tag)
{
VTKM_IS_LIST_TAG(TestListTagUniversal);
//TestListTagUniversal can't be used with for_each on purpose
std::vector<int> found;
std::cout << " Try checking contents" << std::endl;
CheckContains(TestClass<11>(), TestListTagUniversal(), found);
CheckContains(TestClass<21>(), TestListTagUniversal(), found);
CheckContains(TestClass<22>(), TestListTagUniversal(), found);
CheckContains(TestClass<31>(), TestListTagUniversal(), found);
CheckContains(TestClass<32>(), TestListTagUniversal(), found);
CheckContains(TestClass<33>(), TestListTagUniversal(), found);
CheckContains(TestClass<41>(), TestListTagUniversal(), found);
CheckContains(TestClass<42>(), TestListTagUniversal(), found);
CheckContains(TestClass<43>(), TestListTagUniversal(), found);
CheckContains(TestClass<44>(), TestListTagUniversal(), found);
}
void TestLists()
{
std::cout << "Valid List Tag Checks" << std::endl;
@ -176,6 +214,9 @@ void TestLists()
std::cout << "ListTagIntersect" << std::endl;
TryList(vtkm::Vec<int,3>(31,32,33), TestListTagIntersect());
std::cout << "ListTagUniversal" << std::endl;
TryList(vtkm::Vec<int,4>(1,2,3,4), TestListTagUniversal());
}
} // anonymous namespace