Implement old ListTag features with new ListTag implementations

This cleans up the code a bit by removing duplication. More importantly,
it makes sure that the old ListTag functions work with both the new
`List` and old `ListTagBase`.
This commit is contained in:
Kenneth Moreland 2019-12-08 19:20:34 -07:00
parent d5fe4046c5
commit 5cfc14482b
5 changed files with 105 additions and 322 deletions

@ -275,7 +275,7 @@ struct ListHasImpl<vtkm::ListUniversal, T>
/// Becomes `std::true_type` if the `T` is in `List`. `std::false_type` otherwise.
///
template <typename List, typename T>
using ListHas = typename detail::ListHasImpl<List, T>::type;
using ListHas = typename detail::ListHasImpl<internal::AsList<List>, T>::type;
/// Concatinates a set of lists into a single list.
///

@ -14,15 +14,48 @@
#include <vtkm/List.h>
#include <vtkm/internal/ListTagDetail.h>
#include <vtkm/StaticAssert.h>
#include <vtkm/internal/ExportMacros.h>
#include <vtkm/internal/brigand.hpp>
#include <type_traits>
namespace vtkm
{
namespace detail
{
//-----------------------------------------------------------------------------
/// Base class that all ListTag classes inherit from. Helps identify lists
/// in macros like VTKM_IS_LIST_TAG.
///
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;
};
} // namespace detail
//-----------------------------------------------------------------------------
/// A basic tag for a list of typenames. This struct can be subclassed
/// and still behave like a list tag.
template <typename... ArgTypes>
struct VTKM_DEPRECATED(1.6, "ListTagBase replace by List. Note that List cannot be subclassed.")
ListTagBase : detail::ListRoot
{
using list = detail::ListBase<ArgTypes...>;
};
/// A special tag for a list that represents holding all potential values
///
@ -51,7 +84,7 @@ namespace detail
template <typename ListTag>
struct VTKM_DEPRECATED(1.6, "VTKM_IS_LIST_TAG replaced with VTKM_IS_LIST.") ListTagAssert
: internal::ListTagCheck<ListTag>
: internal::IsList<ListTag>
{
};
@ -113,17 +146,13 @@ struct AsListImpl
{
VTKM_STATIC_ASSERT_MSG(ListTagCheck<T>::value,
"Attempted to use something that is not a List with a List operation.");
using type = brigand::wrap<ListTagAsBrigandList<T>, vtkm::List>;
VTKM_DEPRECATED_SUPPRESS_BEGIN
using type = typename std::conditional<std::is_base_of<vtkm::ListTagUniversal, T>::value,
vtkm::ListUniversal,
brigand::wrap<ListTagAsBrigandList<T>, vtkm::List>>::type;
VTKM_DEPRECATED_SUPPRESS_END
};
VTKM_DEPRECATED_SUPPRESS_BEGIN
template <>
struct AsListImpl<vtkm::ListTagUniversal>
{
using type = vtkm::ListUniversal;
};
VTKM_DEPRECATED_SUPPRESS_END
} // namespace internal
@ -166,9 +195,8 @@ template <typename... ListTags>
struct VTKM_DEPRECATED(
1.6,
"ListTagJoin replaced by ListAppend. Note that ListAppend cannot be subclassed.") ListTagJoin
: detail::ListRoot
: vtkm::internal::ListAsListTag<vtkm::ListAppend<ListTags...>>
{
using list = typename detail::ListJoin<internal::ListTagAsBrigandList<ListTags>...>::type;
};
@ -177,25 +205,18 @@ template <typename ListTag, typename Type>
struct VTKM_DEPRECATED(1.6,
"ListTagAppend<List, Type> replaced by ListAppend<List, vtkm::List<Type>. "
"Note that ListAppend cannot be subclassed.") ListTagAppend
: detail::ListRoot
: vtkm::ListTagJoin<ListTag, vtkm::List<Type>>
{
VTKM_DEPRECATED_SUPPRESS_BEGIN
VTKM_IS_LIST_TAG(ListTag);
VTKM_DEPRECATED_SUPPRESS_END
using list = typename detail::ListJoin<internal::ListTagAsBrigandList<ListTag>,
detail::ListBase<Type>>::type;
};
/// Append \c Type to \c ListTag only if \c ListTag does not already contain \c Type.
/// No checks are performed to see if \c ListTag itself has only unique elements.
template <typename ListTag, typename Type>
struct VTKM_DEPRECATED(1.6) ListTagAppendUnique : detail::ListRoot
struct VTKM_DEPRECATED(1.6) ListTagAppendUnique
: std::conditional<vtkm::ListHas<ListTag, Type>::value,
vtkm::internal::ListAsListTag<vtkm::internal::AsList<ListTag>>,
vtkm::ListTagAppend<ListTag, Type>>::type
{
VTKM_DEPRECATED_SUPPRESS_BEGIN
VTKM_IS_LIST_TAG(ListTag);
VTKM_DEPRECATED_SUPPRESS_END
using list =
typename detail::ListAppendUniqueImpl<internal::ListTagAsBrigandList<ListTag>, Type>::type;
};
/// A tag that consists of elements that are found in both tags. This struct
@ -204,14 +225,8 @@ template <typename ListTag1, typename ListTag2>
struct VTKM_DEPRECATED(
1.6,
"ListTagIntersect replaced by ListIntersect. Note that ListIntersect cannot be subclassed.")
ListTagIntersect : detail::ListRoot
ListTagIntersect : vtkm::internal::ListAsListTag<vtkm::ListIntersect<ListTag1, ListTag2>>
{
VTKM_DEPRECATED_SUPPRESS_BEGIN
VTKM_IS_LIST_TAG(ListTag1);
VTKM_IS_LIST_TAG(ListTag2);
VTKM_DEPRECATED_SUPPRESS_END
using list = typename detail::ListIntersect<internal::ListTagAsBrigandList<ListTag1>,
internal::ListTagAsBrigandList<ListTag2>>::type;
};
/// A list tag that consists of each item in another list tag fed into a template that takes
@ -220,13 +235,8 @@ template <typename ListTag, template <typename> class Transform>
struct VTKM_DEPRECATED(
1.6,
"ListTagTransform replaced by ListTransform. Note that ListTransform cannot be subclassed.")
ListTagTransform : detail::ListRoot
ListTagTransform : vtkm::internal::ListAsListTag<vtkm::ListTransform<ListTag, Transform>>
{
VTKM_DEPRECATED_SUPPRESS_BEGIN
VTKM_IS_LIST_TAG(ListTag);
VTKM_DEPRECATED_SUPPRESS_END
using list = brigand::transform<internal::ListTagAsBrigandList<ListTag>,
brigand::bind<Transform, brigand::_1>>;
};
/// A list tag that takes an existing ListTag and a predicate template that is applied to
@ -246,15 +256,19 @@ template <typename ListTag, template <typename> class Predicate>
struct VTKM_DEPRECATED(
1.6,
"ListTagRemoveIf replaced by ListRemoveIf. Note that ListRemoveIf cannot be subclassed.")
ListTagRemoveIf : detail::ListRoot
ListTagRemoveIf : vtkm::internal::ListAsListTag<vtkm::ListRemoveIf<ListTag, Predicate>>
{
VTKM_DEPRECATED_SUPPRESS_BEGIN
VTKM_IS_LIST_TAG(ListTag);
VTKM_DEPRECATED_SUPPRESS_END
using list = brigand::remove_if<internal::ListTagAsBrigandList<ListTag>,
brigand::bind<Predicate, brigand::_1>>;
};
namespace detail
{
// Old stlye ListCrossProduct expects brigand::list instead of vtkm::List. Transform back
template <typename List>
using ListToBrigand = vtkm::ListApply<List, brigand::list>;
} // namespace detail
/// Generate a tag that is the cross product of two other tags. The resulting
/// tag has the form of Tag< brigand::list<A1,B1>, brigand::list<A1,B2> .... >
///
@ -262,15 +276,10 @@ template <typename ListTag1, typename ListTag2>
struct VTKM_DEPRECATED(
1.6,
"ListCrossProduct replaced by ListCross. Note that LIstCross cannot be subclassed.")
ListCrossProduct : detail::ListRoot
ListCrossProduct
: vtkm::internal::ListAsListTag<
vtkm::ListTransform<vtkm::ListCross<ListTag1, ListTag2>, detail::ListToBrigand>>
{
VTKM_DEPRECATED_SUPPRESS_BEGIN
VTKM_IS_LIST_TAG(ListTag1);
VTKM_IS_LIST_TAG(ListTag2);
VTKM_DEPRECATED_SUPPRESS_END
using list =
typename detail::ListCrossProductImpl<internal::ListTagAsBrigandList<ListTag1>,
internal::ListTagAsBrigandList<ListTag2>>::type;
};
/// \brief Checks to see if the given \c Type is in the list pointed to by \c ListTag.
@ -280,12 +289,8 @@ struct VTKM_DEPRECATED(
///
template <typename ListTag, typename Type>
struct VTKM_DEPRECATED(1.6, "ListContains replaced by ListHas.") ListContains
: vtkm::ListHas<ListTag, Type>
{
VTKM_DEPRECATED_SUPPRESS_BEGIN
VTKM_IS_LIST_TAG(ListTag);
VTKM_DEPRECATED_SUPPRESS_END
static constexpr bool value =
detail::ListContainsImpl<Type, internal::ListTagAsBrigandList<ListTag>>::value;
};
/// \brief Finds the type at the given index.

@ -63,7 +63,6 @@ set(headers
IndexTag.h
IndicesExtrude.h
Invocation.h
ListTagDetail.h
Unreachable.h
Variant.h
VariantDetail.h

@ -1,255 +0,0 @@
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt 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 vtk_m_internal_ListTagDetail_h
#define vtk_m_internal_ListTagDetail_h
#if !defined(vtk_m_ListTag_h) && !defined(VTKM_TEST_HEADER_BUILD)
#error ListTagDetail.h must be included from ListTag.h
#endif
#include <vtkm/Deprecated.h>
#include <vtkm/Types.h>
#include <vtkm/internal/brigand.hpp>
namespace vtkm
{
namespace detail
{
//-----------------------------------------------------------------------------
/// Base class that all ListTag classes inherit from. Helps identify lists
/// in macros like VTKM_IS_LIST_TAG.
///
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... ListTags>
struct ListJoin
{
using type = brigand::append<ListTags...>;
};
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>;
};
//-----------------------------------------------------------------------------
template <typename Type, typename List>
struct ListContainsImpl;
//-----------------------------------------------------------------------------
template <typename Type>
struct ListContainsImpl<Type, brigand::empty_sequence>
{
static constexpr bool value = false;
};
//-----------------------------------------------------------------------------
template <typename Type>
struct ListContainsImpl<Type, brigand::list<vtkm::detail::UniversalTag>>
{
static constexpr bool value = true;
};
//-----------------------------------------------------------------------------
template <typename Type, typename T1>
struct ListContainsImpl<Type, brigand::list<T1>>
{
static constexpr bool value = std::is_same<Type, T1>::value;
};
//-----------------------------------------------------------------------------
template <typename Type, typename T1, typename T2>
struct ListContainsImpl<Type, brigand::list<T1, T2>>
{
static constexpr bool value = std::is_same<Type, T1>::value || std::is_same<Type, T2>::value;
};
//-----------------------------------------------------------------------------
template <typename Type, typename T1, typename T2, typename T3>
struct ListContainsImpl<Type, brigand::list<T1, T2, T3>>
{
static constexpr bool value =
std::is_same<Type, T1>::value || std::is_same<Type, T2>::value || std::is_same<Type, T3>::value;
};
//-----------------------------------------------------------------------------
template <typename Type, typename T1, typename T2, typename T3, typename T4>
struct ListContainsImpl<Type, brigand::list<T1, T2, T3, T4>>
{
static constexpr bool value = std::is_same<Type, T1>::value || std::is_same<Type, T2>::value ||
std::is_same<Type, T3>::value || std::is_same<Type, T4>::value;
};
//-----------------------------------------------------------------------------
template <typename Type, typename List>
struct ListContainsImpl
{
using find_result = brigand::find<List, std::is_same<brigand::_1, Type>>;
using size = brigand::size<find_result>;
static constexpr bool value = (size::value != 0);
};
//-----------------------------------------------------------------------------
template <typename BrigandList>
struct ListSizeImpl;
template <typename... Ts>
struct ListSizeImpl<brigand::list<Ts...>>
{
static constexpr vtkm::IdComponent value = vtkm::IdComponent{ sizeof...(Ts) };
};
//-----------------------------------------------------------------------------
template <class T, class U, class ListTag>
struct intersect_tags
{
using has_u = ListContainsImpl<U, ListTag>;
using type = typename std::conditional<has_u::value, brigand::push_back<T, U>, T>::type;
};
//-----------------------------------------------------------------------------
template <typename ListTag1, typename ListTag2>
struct ListIntersect
{
using type =
brigand::fold<ListTag1,
brigand::list<>,
intersect_tags<brigand::_state, brigand::_element, brigand::pin<ListTag2>>>;
};
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>
{
using type = SameListTag;
};
template <typename Functor, typename... Args>
VTKM_CONT void ListForEachImpl(Functor&&, brigand::list<>, Args&&...)
{
}
template <typename Functor, typename T1, typename... Args>
VTKM_CONT void ListForEachImpl(Functor&& f, brigand::list<T1>, Args&&... args)
{
f(T1{}, std::forward<Args>(args)...);
}
template <typename Functor, typename T1, typename T2, typename... Args>
VTKM_CONT void ListForEachImpl(Functor&& f, brigand::list<T1, T2>, Args&&... args)
{
f(T1{}, std::forward<Args>(args)...);
f(T2{}, std::forward<Args>(args)...);
}
template <typename Functor, typename T1, typename T2, typename T3, typename... Args>
VTKM_CONT void ListForEachImpl(Functor&& f, brigand::list<T1, T2, T3>, Args&&... args)
{
f(T1{}, std::forward<Args>(args)...);
f(T2{}, std::forward<Args>(args)...);
f(T3{}, std::forward<Args>(args)...);
}
template <typename Functor,
typename T1,
typename T2,
typename T3,
typename T4,
typename... ArgTypes,
typename... Args>
VTKM_CONT void ListForEachImpl(Functor&& f,
brigand::list<T1, T2, T3, T4, ArgTypes...>&&,
Args&&... args)
{
f(T1{}, std::forward<Args>(args)...);
f(T2{}, std::forward<Args>(args)...);
f(T3{}, std::forward<Args>(args)...);
f(T4{}, std::forward<Args>(args)...);
ListForEachImpl(
std::forward<Functor>(f), brigand::list<ArgTypes...>{}, std::forward<Args>(args)...);
}
template <typename R1, typename R2>
struct ListCrossProductImpl
{
// This is a lazy Cartesian product generator.
// This version was settled on as being the best default
// version as all compilers including Intel handle this
// implementation without issue for very large cross products
using type = brigand::reverse_fold<
brigand::list<R1, R2>,
brigand::list<brigand::list<>>,
brigand::lazy::join<brigand::lazy::transform<
brigand::_2,
brigand::defer<brigand::lazy::join<brigand::lazy::transform<
brigand::parent<brigand::_1>,
brigand::defer<brigand::bind<
brigand::list,
brigand::lazy::push_front<brigand::_1, brigand::parent<brigand::_1>>>>>>>>>>;
};
//-----------------------------------------------------------------------------
template <typename List, typename Type>
struct ListAppendUniqueImpl
{
using type = typename std::conditional<ListContainsImpl<Type, List>::value,
List,
typename ListJoin<List, ListBase<Type>>::type>::type;
};
} // namespace detail
//-----------------------------------------------------------------------------
/// A basic tag for a list of typenames. This struct can be subclassed
/// and still behave like a list tag.
template <typename... ArgTypes>
struct VTKM_DEPRECATED(1.6, "ListTagBase replace by List. Note that List cannot be subclassed.")
ListTagBase : detail::ListRoot
{
using list = detail::ListBase<ArgTypes...>;
};
}
#endif //vtk_m_internal_ListTagDetail_h

@ -34,30 +34,45 @@ struct TestClass
struct TestListTag1 : vtkm::ListTagBase<TestClass<11>>
{
};
using TestListTagBackward1 = vtkm::List<TestClass<11>>;
struct TestListTag2 : vtkm::ListTagBase<TestClass<21>, TestClass<22>>
{
};
using TestListTagBackward2 = vtkm::List<TestClass<21>, TestClass<22>>;
struct TestListTag3 : vtkm::ListTagBase<TestClass<31>, TestClass<32>, TestClass<33>>
{
};
using TestListTagBackward3 = vtkm::List<TestClass<31>, TestClass<32>, TestClass<33>>;
struct TestListTag4 : vtkm::ListTagBase<TestClass<41>, TestClass<42>, TestClass<43>, TestClass<44>>
{
};
using TestListTagBackward4 = vtkm::List<TestClass<41>, TestClass<42>, TestClass<43>, TestClass<44>>;
struct TestListTagJoin : vtkm::ListTagJoin<TestListTag3, TestListTag1>
{
};
struct TestListTagJoinBackward : vtkm::ListTagJoin<TestListTagBackward3, TestListTagBackward1>
{
};
struct TestListTagIntersect : vtkm::ListTagIntersect<TestListTag3, TestListTagJoin>
{
};
struct TestListTagIntersectBackward
: vtkm::ListTagIntersect<TestListTagBackward3, TestListTagJoinBackward>
{
};
struct TestListTagCrossProduct : vtkm::ListCrossProduct<TestListTag3, TestListTag1>
{
};
struct TestListTagCrossProductBackward
: vtkm::ListCrossProduct<TestListTagBackward3, TestListTagBackward1>
{
};
struct TestListTagUniversal : vtkm::ListTagUniversal
{
@ -66,14 +81,25 @@ struct TestListTagUniversal : vtkm::ListTagUniversal
struct TestListTagAppend : vtkm::ListTagAppend<TestListTag3, TestClass<34>>
{
};
struct TestListTagAppendBackward : vtkm::ListTagAppend<TestListTagBackward3, TestClass<34>>
{
};
struct TestListTagAppendUnique1 : vtkm::ListTagAppendUnique<TestListTag3, TestClass<32>>
{
};
struct TestListTagAppendUniqueBackward1
: vtkm::ListTagAppendUnique<TestListTagBackward3, TestClass<32>>
{
};
struct TestListTagAppendUnique2 : vtkm::ListTagAppendUnique<TestListTagAppendUnique1, TestClass<34>>
{
};
struct TestListTagAppendUniqueBackward2
: vtkm::ListTagAppendUnique<TestListTagAppendUniqueBackward1, TestClass<34>>
{
};
template <typename T>
struct DoubleTransformImpl;
@ -89,6 +115,9 @@ using DoubleTransform = typename DoubleTransformImpl<T>::type;
struct TestListTagTransform : vtkm::ListTagTransform<TestListTag4, DoubleTransform>
{
};
struct TestListTagTransformBackward : vtkm::ListTagTransform<TestListTagBackward4, DoubleTransform>
{
};
template <typename T>
struct EvenPredicate;
@ -100,6 +129,9 @@ struct EvenPredicate<TestClass<N>> : std::integral_constant<bool, (N % 2) == 0>
struct TestListTagRemoveIf : vtkm::ListTagRemoveIf<TestListTag4, EvenPredicate>
{
};
struct TestListTagRemoveIfBackward : vtkm::ListTagRemoveIf<TestListTagBackward4, EvenPredicate>
{
};
template <int N, int M>
std::pair<int, int> test_number(brigand::list<TestClass<N>, TestClass<M>>)
@ -150,16 +182,9 @@ void CheckSame(const vtkm::Vec<T, N>& expected, const std::vector<T>& found)
template <int N, typename ListTag>
void CheckContains(TestClass<N>, ListTag, const std::vector<int>& contents)
{
//Use intersect to verify at compile time that ListTag contains TestClass<N>
using intersectWith = vtkm::ListTagBase<TestClass<N>>;
using intersectResult =
vtkm::internal::ListTagAsBrigandList<vtkm::ListTagIntersect<intersectWith, ListTag>>;
constexpr bool intersectContains = (brigand::size<intersectResult>::value != 0);
bool listContains = vtkm::ListContains<ListTag, TestClass<N>>::value;
bool shouldContain = std::find(contents.begin(), contents.end(), N) != contents.end();
VTKM_TEST_ASSERT(intersectContains == shouldContain, "ListTagIntersect check failed.");
VTKM_TEST_ASSERT(listContains == shouldContain, "ListContains check failed.");
}
@ -268,28 +293,37 @@ void TestLists()
std::cout << "ListTagJoin" << std::endl;
TryList(vtkm::Vec<int, 4>(31, 32, 33, 11), TestListTagJoin());
TryList(vtkm::Vec<int, 4>(31, 32, 33, 11), TestListTagJoinBackward());
std::cout << "ListTagIntersect" << std::endl;
TryList(vtkm::Vec<int, 3>(31, 32, 33), TestListTagIntersect());
TryList(vtkm::Vec<int, 3>(31, 32, 33), TestListTagIntersectBackward());
std::cout << "ListTagCrossProduct" << std::endl;
TryList(vtkm::Vec<std::pair<int, int>, 3>({ 31, 11 }, { 32, 11 }, { 33, 11 }),
TestListTagCrossProduct());
TryList(vtkm::Vec<std::pair<int, int>, 3>({ 31, 11 }, { 32, 11 }, { 33, 11 }),
TestListTagCrossProductBackward());
std::cout << "ListTagAppend" << std::endl;
TryList(vtkm::Vec<int, 4>(31, 32, 33, 34), TestListTagAppend());
TryList(vtkm::Vec<int, 4>(31, 32, 33, 34), TestListTagAppendBackward());
std::cout << "ListTagAppendUnique1" << std::endl;
TryList(vtkm::Vec<int, 3>(31, 32, 33), TestListTagAppendUnique1());
TryList(vtkm::Vec<int, 3>(31, 32, 33), TestListTagAppendUniqueBackward1());
std::cout << "ListTagAppendUnique2" << std::endl;
TryList(vtkm::Vec<int, 4>(31, 32, 33, 34), TestListTagAppendUnique2());
TryList(vtkm::Vec<int, 4>(31, 32, 33, 34), TestListTagAppendUniqueBackward2());
std::cout << "ListTagTransform" << std::endl;
TryList(vtkm::Vec<int, 4>(82, 84, 86, 88), TestListTagTransform());
TryList(vtkm::Vec<int, 4>(82, 84, 86, 88), TestListTagTransformBackward());
std::cout << "ListTagRemoveIf" << std::endl;
TryList(vtkm::Vec<int, 2>(41, 43), TestListTagRemoveIf());
TryList(vtkm::Vec<int, 2>(41, 43), TestListTagRemoveIfBackward());