vtk-m/vtkm/ListTag.h

153 lines
4.4 KiB
C
Raw Normal View History

//============================================================================
// 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.
//
// Copyright 2014 Sandia Corporation.
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_ListTag_h
#define vtk_m_ListTag_h
#include <vtkm/internal/ListTagDetail.h>
#include <vtkm/internal/ExportMacros.h>
VTKM_THIRDPARTY_PRE_INCLUDE
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_base_of.hpp>
VTKM_THIRDPARTY_POST_INCLUDE
namespace vtkm {
namespace internal {
template<typename ListTag>
struct ListTagCheck
{
static const bool Valid =
boost::is_base_of<vtkm::detail::ListRoot,ListTag>::value;
};
} // 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.)
///
#define VTKM_IS_LIST_TAG(tag) \
VTKM_THIRDPARTY_PRE_INCLUDE \
BOOST_STATIC_ASSERT_MSG( \
::vtkm::internal::ListTagCheck<tag>::Valid, \
"Provided type is not a valid VTK-m list tag.") \
VTKM_THIRDPARTY_POST_INCLUDE
namespace detail {
template<typename ListTag1, typename ListTag2>
struct ListJoin { };
} // namespace detail
/// A special tag for an empty list.
///
struct ListTagEmpty : detail::ListRoot {
typedef detail::ListBase<void()> List;
};
/// A tag that is a construction of two other tags joined together. This struct
/// can be subclassed and still behave like a list tag.
template<typename ListTag1, typename ListTag2>
struct ListTagJoin : detail::ListRoot {
typedef detail::ListJoin<ListTag1, ListTag2> List;
};
template<typename Functor, typename ListTag>
VTKM_CONT_EXPORT
void ListForEach(Functor &f, ListTag);
template<typename Functor, typename ListTag>
VTKM_CONT_EXPORT
void ListForEach(const Functor &f, ListTag);
namespace detail {
template<typename Functor, typename ListTag1, typename ListTag2>
VTKM_CONT_EXPORT
void ListForEachImpl(Functor &f, ListJoin<ListTag1, ListTag2>)
{
vtkm::ListForEach(f, ListTag1());
vtkm::ListForEach(f, ListTag2());
}
template<typename Functor, typename ListTag1, typename ListTag2>
VTKM_CONT_EXPORT
void ListForEachImpl(const Functor &f, ListJoin<ListTag1, ListTag2>)
{
vtkm::ListForEach(f, ListTag1());
vtkm::ListForEach(f, ListTag2());
}
} // namespace detail
/// For each typename represented by the list tag, call the functor with a
/// default instance of that type.
///
template<typename Functor, typename ListTag>
VTKM_CONT_EXPORT
void ListForEach(Functor &f, ListTag)
{
VTKM_IS_LIST_TAG(ListTag);
detail::ListForEachImpl(f, typename ListTag::List());
}
/// For each typename represented by the list tag, call the functor with a
/// default instance of that type.
///
template<typename Functor, typename ListTag>
VTKM_CONT_EXPORT
void ListForEach(const Functor &f, ListTag)
{
VTKM_IS_LIST_TAG(ListTag);
detail::ListForEachImpl(f, typename ListTag::List());
}
/// Checks to see if the given \c Type is in the list pointed to by \c ListTag.
/// There is a static boolean named \c value that is set to true if the type is
/// contained in the list and false otherwise.
///
template<typename ListTag, typename Type>
struct ListContains
{
VTKM_IS_LIST_TAG(ListTag);
static const bool value =
detail::ListContainsImpl<typename ListTag::List,Type>::value;
};
namespace detail {
template<typename Type, typename ListTag1, typename ListTag2>
struct ListContainsImpl<ListJoin<ListTag1,ListTag2>, Type>
{
static const bool value = (vtkm::ListContains<ListTag1,Type>::value ||
vtkm::ListContains<ListTag2,Type>::value);
};
} // namespace detail
} // namespace vtkm
#endif //vtk_m_ListTag_h