2014-03-31 21:28:09 +00:00
|
|
|
//============================================================================
|
|
|
|
// Copyright (c) Kitware, Inc.
|
|
|
|
// All rights reserved.
|
|
|
|
// See LICENSE.txt for details.
|
2019-04-15 23:24:21 +00:00
|
|
|
//
|
2014-03-31 21:28:09 +00:00
|
|
|
// 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_ListTag_h
|
|
|
|
#define vtk_m_ListTag_h
|
|
|
|
|
2019-12-04 14:30:47 +00:00
|
|
|
#include <vtkm/List.h>
|
|
|
|
|
2014-10-08 18:53:01 +00:00
|
|
|
#include <vtkm/internal/ListTagDetail.h>
|
|
|
|
|
2015-09-17 19:45:35 +00:00
|
|
|
#include <vtkm/StaticAssert.h>
|
2014-03-31 21:28:09 +00:00
|
|
|
#include <vtkm/internal/ExportMacros.h>
|
|
|
|
|
2016-08-29 15:13:00 +00:00
|
|
|
#include <type_traits>
|
2014-10-22 13:24:04 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
namespace vtkm
|
|
|
|
{
|
2014-03-31 21:28:09 +00:00
|
|
|
|
2019-12-04 14:30:47 +00:00
|
|
|
/// 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>;
|
|
|
|
};
|
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
namespace internal
|
|
|
|
{
|
2014-10-22 13:24:04 +00:00
|
|
|
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename ListTag>
|
|
|
|
struct ListTagCheck : std::is_base_of<vtkm::detail::ListRoot, ListTag>
|
2014-10-22 13:24:04 +00:00
|
|
|
{
|
2018-02-22 16:34:08 +00:00
|
|
|
static constexpr bool Valid = std::is_base_of<vtkm::detail::ListRoot, ListTag>::value;
|
2014-10-22 13:24:04 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace internal
|
|
|
|
|
|
|
|
/// Checks that the argument is a proper list tag. This is a handy concept
|
|
|
|
/// check for functions and classes to make sure that a template argument is
|
|
|
|
/// actually a device adapter tag. (You can get weird errors elsewhere in the
|
|
|
|
/// code when a mistake is made.)
|
|
|
|
///
|
2017-05-18 14:29:41 +00:00
|
|
|
#define VTKM_IS_LIST_TAG(tag) \
|
|
|
|
VTKM_STATIC_ASSERT_MSG((::vtkm::internal::ListTagCheck<tag>::value), \
|
|
|
|
"Provided type is not a valid VTK-m list tag.")
|
2014-10-22 16:35:56 +00:00
|
|
|
|
2019-07-15 03:35:45 +00:00
|
|
|
namespace internal
|
|
|
|
{
|
|
|
|
|
|
|
|
namespace detail
|
|
|
|
{
|
|
|
|
|
|
|
|
template <typename ListTag>
|
|
|
|
struct ListTagAsBrigandListImpl
|
|
|
|
{
|
|
|
|
VTKM_IS_LIST_TAG(ListTag);
|
|
|
|
using type = typename ListTag::list;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace detail
|
|
|
|
|
|
|
|
/// Converts a ListTag to a brigand::list.
|
|
|
|
///
|
|
|
|
template <typename ListTag>
|
|
|
|
using ListTagAsBrigandList = typename detail::ListTagAsBrigandListImpl<ListTag>::type;
|
|
|
|
|
2019-12-04 14:30:47 +00:00
|
|
|
template <typename List>
|
|
|
|
using ListAsListTag = brigand::wrap<List, vtkm::ListTagBase>;
|
|
|
|
|
|
|
|
// This allows the new `List` operations work on `ListTag`s.
|
|
|
|
template <typename T>
|
|
|
|
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>;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct AsListImpl<vtkm::ListTagUniversal>
|
|
|
|
{
|
|
|
|
using type = vtkm::ListUniversal;
|
|
|
|
};
|
|
|
|
|
2019-07-15 03:35:45 +00:00
|
|
|
} // namespace internal
|
|
|
|
|
|
|
|
|
|
|
|
namespace detail
|
|
|
|
{
|
|
|
|
|
|
|
|
template <typename BrigandList, template <typename...> class Target>
|
|
|
|
struct ListTagApplyImpl;
|
|
|
|
|
|
|
|
template <typename... Ts, template <typename...> class Target>
|
|
|
|
struct ListTagApplyImpl<brigand::list<Ts...>, Target>
|
|
|
|
{
|
|
|
|
using type = Target<Ts...>;
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace detail
|
|
|
|
|
|
|
|
/// \brief Applies the list of types to a template.
|
|
|
|
///
|
|
|
|
/// Given a ListTag and a templated class, returns the class instantiated with the types
|
|
|
|
/// represented by the ListTag.
|
|
|
|
///
|
|
|
|
template <typename ListTag, template <typename...> class Target>
|
|
|
|
using ListTagApply =
|
2019-07-20 04:23:54 +00:00
|
|
|
typename detail::ListTagApplyImpl<internal::ListTagAsBrigandList<ListTag>, Target>::type;
|
2019-07-15 03:35:45 +00:00
|
|
|
|
2014-05-14 21:05:38 +00:00
|
|
|
/// A special tag for an empty list.
|
|
|
|
///
|
2017-05-18 14:29:41 +00:00
|
|
|
struct ListTagEmpty : detail::ListRoot
|
|
|
|
{
|
2016-03-03 20:58:09 +00:00
|
|
|
using list = vtkm::detail::ListBase<>;
|
2014-03-31 21:28:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// A tag that is a construction of two other tags joined together. This struct
|
|
|
|
/// can be subclassed and still behave like a list tag.
|
2019-09-05 16:41:52 +00:00
|
|
|
template <typename... ListTags>
|
2017-05-18 14:29:41 +00:00
|
|
|
struct ListTagJoin : detail::ListRoot
|
|
|
|
{
|
2019-09-05 16:41:52 +00:00
|
|
|
using list = typename detail::ListJoin<internal::ListTagAsBrigandList<ListTags>...>::type;
|
2014-03-31 21:28:09 +00:00
|
|
|
};
|
|
|
|
|
2018-06-21 17:35:57 +00:00
|
|
|
|
|
|
|
/// A tag that is constructed by appending \c Type to \c ListTag.
|
|
|
|
template <typename ListTag, typename Type>
|
|
|
|
struct ListTagAppend : detail::ListRoot
|
|
|
|
{
|
2019-07-15 03:35:45 +00:00
|
|
|
VTKM_IS_LIST_TAG(ListTag);
|
|
|
|
using list = typename detail::ListJoin<internal::ListTagAsBrigandList<ListTag>,
|
|
|
|
detail::ListBase<Type>>::type;
|
2018-06-21 17:35:57 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/// Append \c Type to \c ListTag only if \c ListTag does not already contain \c Type.
|
2018-08-07 21:50:41 +00:00
|
|
|
/// No checks are performed to see if \c ListTag itself has only unique elements.
|
2018-06-21 17:35:57 +00:00
|
|
|
template <typename ListTag, typename Type>
|
|
|
|
struct ListTagAppendUnique : detail::ListRoot
|
|
|
|
{
|
2019-07-15 03:35:45 +00:00
|
|
|
VTKM_IS_LIST_TAG(ListTag);
|
|
|
|
using list =
|
|
|
|
typename detail::ListAppendUniqueImpl<internal::ListTagAsBrigandList<ListTag>, Type>::type;
|
2018-06-21 17:35:57 +00:00
|
|
|
};
|
|
|
|
|
2017-11-06 15:12:49 +00:00
|
|
|
/// A tag that consists of elements that are found in both tags. This struct
|
2016-12-29 21:00:52 +00:00
|
|
|
/// can be subclassed and still behave like a list tag.
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename ListTag1, typename ListTag2>
|
|
|
|
struct ListTagIntersect : detail::ListRoot
|
|
|
|
{
|
2019-07-15 03:35:45 +00:00
|
|
|
VTKM_IS_LIST_TAG(ListTag1);
|
|
|
|
VTKM_IS_LIST_TAG(ListTag2);
|
|
|
|
using list = typename detail::ListIntersect<internal::ListTagAsBrigandList<ListTag1>,
|
|
|
|
internal::ListTagAsBrigandList<ListTag2>>::type;
|
2016-12-29 21:00:52 +00:00
|
|
|
};
|
|
|
|
|
2019-07-15 04:51:28 +00:00
|
|
|
/// A list tag that consists of each item in another list tag fed into a template that takes
|
|
|
|
/// a single parameter.
|
|
|
|
template <typename ListTag, template <typename> class Transform>
|
|
|
|
struct ListTagTransform : detail::ListRoot
|
|
|
|
{
|
|
|
|
VTKM_IS_LIST_TAG(ListTag);
|
|
|
|
using list = brigand::transform<internal::ListTagAsBrigandList<ListTag>,
|
|
|
|
brigand::bind<Transform, brigand::_1>>;
|
|
|
|
};
|
|
|
|
|
2019-10-31 20:32:17 +00:00
|
|
|
/// A list tag that takes an existing ListTag and a predicate template that is applied to
|
|
|
|
/// each type in the ListTag. Any type in the ListTag that has a value element equal to true
|
|
|
|
/// (the equivalent of std::true_type), that item will be removed from the list. For example
|
|
|
|
/// the following type
|
|
|
|
///
|
|
|
|
/// ```cpp
|
|
|
|
/// vtkm::ListTagRemoveIf<vtkm::ListTagBase<int, float, long long, double>, std::is_integral>
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// resolves to a ListTag that is equivalent to `vtkm::ListTag<float, double>` because
|
|
|
|
/// `std::is_integral<int>` and `std::is_integral<long long>` resolve to `std::true_type`
|
|
|
|
/// whereas `std::is_integral<float>` and `std::is_integral<double>` resolve to
|
|
|
|
/// `std::false_type`.
|
|
|
|
template <typename ListTag, template <typename> class Predicate>
|
|
|
|
struct ListTagRemoveIf : detail::ListRoot
|
|
|
|
{
|
|
|
|
VTKM_IS_LIST_TAG(ListTag);
|
|
|
|
using list = brigand::remove_if<internal::ListTagAsBrigandList<ListTag>,
|
|
|
|
brigand::bind<Predicate, brigand::_1>>;
|
|
|
|
};
|
|
|
|
|
2017-11-06 15:12:49 +00:00
|
|
|
/// Generate a tag that is the cross product of two other tags. The resulting
|
2019-07-15 03:35:45 +00:00
|
|
|
/// tag has the form of Tag< brigand::list<A1,B1>, brigand::list<A1,B2> .... >
|
2017-11-06 15:12:49 +00:00
|
|
|
///
|
|
|
|
template <typename ListTag1, typename ListTag2>
|
|
|
|
struct ListCrossProduct : detail::ListRoot
|
|
|
|
{
|
2019-07-15 03:35:45 +00:00
|
|
|
VTKM_IS_LIST_TAG(ListTag1);
|
|
|
|
VTKM_IS_LIST_TAG(ListTag2);
|
2017-11-06 15:12:49 +00:00
|
|
|
using list =
|
2019-07-15 03:35:45 +00:00
|
|
|
typename detail::ListCrossProductImpl<internal::ListTagAsBrigandList<ListTag1>,
|
|
|
|
internal::ListTagAsBrigandList<ListTag2>>::type;
|
2017-11-06 15:12:49 +00:00
|
|
|
};
|
|
|
|
|
2019-07-14 23:38:30 +00:00
|
|
|
/// \brief Checks to see if the given \c Type is in the list pointed to by \c ListTag.
|
|
|
|
///
|
2014-10-22 16:35:56 +00:00
|
|
|
/// There is a static boolean named \c value that is set to true if the type is
|
|
|
|
/// contained in the list and false otherwise.
|
|
|
|
///
|
2017-05-18 14:29:41 +00:00
|
|
|
template <typename ListTag, typename Type>
|
2014-10-22 16:35:56 +00:00
|
|
|
struct ListContains
|
|
|
|
{
|
|
|
|
VTKM_IS_LIST_TAG(ListTag);
|
2019-07-15 03:35:45 +00:00
|
|
|
static constexpr bool value =
|
|
|
|
detail::ListContainsImpl<Type, internal::ListTagAsBrigandList<ListTag>>::value;
|
2014-10-22 16:35:56 +00:00
|
|
|
};
|
|
|
|
|
2019-07-14 23:38:30 +00:00
|
|
|
/// \brief Finds the type at the given index.
|
|
|
|
///
|
|
|
|
/// This struct contains subtype \c type that resolves to the type at the given index.
|
|
|
|
///
|
|
|
|
template <typename ListTag, vtkm::IdComponent Index>
|
|
|
|
struct ListTypeAt
|
|
|
|
{
|
|
|
|
VTKM_IS_LIST_TAG(ListTag);
|
2019-07-15 03:35:45 +00:00
|
|
|
using type = brigand::at<internal::ListTagAsBrigandList<ListTag>,
|
|
|
|
std::integral_constant<vtkm::IdComponent, Index>>;
|
2019-07-14 23:38:30 +00:00
|
|
|
};
|
|
|
|
|
2014-03-31 21:28:09 +00:00
|
|
|
} // namespace vtkm
|
|
|
|
|
|
|
|
#endif //vtk_m_ListTag_h
|