Use c++11 variadic templates as storage of ListTags.

This commit is contained in:
Robert Maynard 2016-03-03 15:58:09 -05:00
parent 8cb295d6ca
commit 7ad88b6e5c
10 changed files with 2439 additions and 1555 deletions

@ -76,3 +76,4 @@ CMake/FindTBB.cmake
CMake/FindGLEW.cmake
vtkm/cont/tbb/internal/parallel_sort.h
vtkm/testing/OptionParser.h
vtkm/internal/brigand.hpp

@ -32,7 +32,7 @@ namespace vtkm {
namespace internal {
template<typename ListTag>
struct ListTagCheck
struct ListTagCheck : std::is_base_of<vtkm::detail::ListRoot,ListTag>
{
static VTKM_CONSTEXPR bool Valid = std::is_base_of<vtkm::detail::ListRoot,
ListTag>::value;
@ -47,57 +47,23 @@ struct ListTagCheck
///
#define VTKM_IS_LIST_TAG(tag) \
VTKM_STATIC_ASSERT_MSG( \
(::vtkm::internal::ListTagCheck<tag>::Valid), \
(::vtkm::internal::ListTagCheck<tag>::value), \
"Provided type is not a valid VTK-m list tag.")
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;
using list = vtkm::detail::ListBase<>;
};
/// 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;
using list = typename detail::ListJoin<ListTag1,ListTag2>::type;
};
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.
///
@ -106,7 +72,7 @@ VTKM_CONT_EXPORT
void ListForEach(Functor &f, ListTag)
{
VTKM_IS_LIST_TAG(ListTag);
detail::ListForEachImpl(f, typename ListTag::List());
detail::ListForEachImpl(f, typename ListTag::list());
}
/// For each typename represented by the list tag, call the functor with a
@ -117,7 +83,7 @@ VTKM_CONT_EXPORT
void ListForEach(const Functor &f, ListTag)
{
VTKM_IS_LIST_TAG(ListTag);
detail::ListForEachImpl(f, typename ListTag::List());
detail::ListForEachImpl(f, typename ListTag::list());
}
/// Checks to see if the given \c Type is in the list pointed to by \c ListTag.
@ -128,20 +94,10 @@ template<typename ListTag, typename Type>
struct ListContains
{
VTKM_IS_LIST_TAG(ListTag);
static const bool value =
detail::ListContainsImpl<typename ListTag::List,Type>::value;
static constexpr bool value =
detail::ListContainsImpl<Type,typename ListTag::list>::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

@ -62,15 +62,15 @@ typedef vtkm::cont::ArrayHandleCompositeVectorType<
/// by default (unless it is defined before including VTK-m headers.
///
struct StorageListTagCoordinateSystemDefault
: vtkm::ListTagJoin<
VTKM_DEFAULT_STORAGE_LIST_TAG,
vtkm::ListTagBase<vtkm::cont::ArrayHandleUniformPointCoordinates::StorageTag,
: vtkm::ListTagBase<
vtkm::cont::StorageTagBasic,
vtkm::cont::ArrayHandleUniformPointCoordinates::StorageTag,
detail::ArrayHandleCompositeVectorFloat32_3Default::StorageTag,
detail::ArrayHandleCompositeVectorFloat64_3Default::StorageTag,
vtkm::cont::ArrayHandleCartesianProduct<
vtkm::cont::ArrayHandle<vtkm::FloatDefault>,
vtkm::cont::ArrayHandle<vtkm::FloatDefault>,
vtkm::cont::ArrayHandle<vtkm::FloatDefault> >::StorageTag > >
vtkm::cont::ArrayHandle<vtkm::FloatDefault> >::StorageTag >
{ };
typedef vtkm::cont::DynamicArrayHandleBase<

@ -471,6 +471,7 @@ struct DynamicArrayHandleTryType {
typedef DynamicArrayHandleTryStorage<Functor, Type> TryStorageType;
TryStorageType tryStorage =
TryStorageType(*this->Array, this->Function);
vtkm::ListForEach(tryStorage, StorageList());
if (tryStorage.FoundCast)
{
@ -524,6 +525,7 @@ void DynamicArrayHandleBase<VTKM_DEFAULT_TYPE_LIST_TAG,
// the default one, and no reason to do an atomic increment and increase
// library size, and reduce performance
TryTypeType tryType = TryTypeType(*this, f);
vtkm::ListForEach(tryType, VTKM_DEFAULT_TYPE_LIST_TAG());
if (!tryType.FoundCast)
{

@ -337,6 +337,7 @@ void DynamicCellSetBase<CellSetList>::CastAndCall(const Functor &f) const
{
typedef detail::DynamicCellSetTryCellSet<Functor> TryCellSetType;
TryCellSetType tryCellSet = TryCellSetType(this->CellSetContainer.get(), f);
vtkm::ListForEach(tryCellSet, CellSetList());
if (!tryCellSet.FoundCast)
{

@ -66,7 +66,6 @@ vtkm_declare_headers(${headers})
vtkm_pyexpander_generated_file(FunctionInterfaceDetailPre.h)
vtkm_pyexpander_generated_file(FunctionInterfaceDetailPost.h)
vtkm_pyexpander_generated_file(ListTagDetail.h)
add_subdirectory(testing)

File diff suppressed because it is too large Load Diff

@ -1,197 +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.
//
// 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.
//============================================================================
$# This file uses the pyexpander macro processing utility to build the
$# FunctionInterface facilities that use a variable number of arguments.
$# Information, documentation, and downloads for pyexpander can be found at:
$#
$# http://pyexpander.sourceforge.net/
$#
$# To build the source code, execute the following (after installing
$# pyexpander, of course):
$#
$# expander.py ListTagDetail.h.in > ListTagDetail.h
$#
$# Ignore the following comment. It is meant for the generated file.
// **** DO NOT EDIT THIS FILE!!! ****
// This file is automatically generated by FunctionInterfaceDetailPre.h.in
#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/Types.h>
$py(max_base_list=15)\
#define VTKM_MAX_BASE_LIST $(max_base_list)
$# Python commands used in template expansion.
$py(
def comma_if(flag):
if flag:
return ','
else:
return '';
def template_params(num_params, name='T', start=1, default=''):
if num_params < start:
return ''
result = 'typename %s%d%s' % (name, start, default)
for param in xrange(start+1, num_params+1):
result += ',\n typename %s%d%s' % (name, param, default)
return result
def param_list(num_params, name='T', start=1):
if num_params < start:
return ''
result = '%s%d' % (name, start)
for param in xrange(start+1, num_params+1):
result += ',%s%d' % (name, param)
return result
def signature(num_params, name='T', return_type='void', start=1):
result = '%s(' % return_type
if num_params >= start:
result += '%s%d' % (name, start)
for param in xrange(start+1, num_params+1):
result += ',%s%d' % (name, param)
result += ')'
return result
)\
$#
$extend(comma_if, param_list, template_params, signature)\
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<typename signature>
struct ListBase { };
//-----------------------------------------------------------------------------
template<typename Functor>
VTKM_CONT_EXPORT
void ListForEachImpl(const Functor &, ListBase<void()>) { }
$for(num_params in xrange(1, max_base_list+1))\
template<typename Functor,
$template_params(num_params)>
VTKM_CONT_EXPORT
void ListForEachImpl(Functor &f, ListBase<void($param_list(num_params))>)
{
$for(param_index in range(1, num_params+1))\
f(T$(param_index)());
$endfor\
}
template<typename Functor,
$template_params(num_params)>
VTKM_CONT_EXPORT
void ListForEachImpl(const Functor &f, ListBase<void($param_list(num_params))>)
{
$for(param_index in range(1, num_params+1))\
f(T$(param_index)());
$endfor\
}
$endfor\
//-----------------------------------------------------------------------------
template<typename List, typename Type>
struct ListContainsImpl;
template<typename Type>
struct ListContainsImpl<ListBase<void()>, Type>
{
static const bool value = false;
};
template<typename Type>
struct ListContainsImpl<ListBase<void(Type)>, Type>
{
static const bool value = true;
};
template<typename Type, typename T1>
struct ListContainsImpl<ListBase<void(T1)>, Type>
{
static const bool value = false;
};
$for(num_params in xrange(2, max_base_list+1))\
template<typename Type,
$template_params(num_params, start=2)>
struct ListContainsImpl<ListBase<void(Type,$param_list(num_params, start=2))>, Type>
{
static const bool value = true;
};
template<typename Type,
$template_params(num_params)>
struct ListContainsImpl<ListBase<$signature(num_params)>, Type>
{
static const bool value =
ListContainsImpl<ListBase<$signature(num_params, start=2)>, Type>::value;
};
$endfor\
} // namespace detail
//-----------------------------------------------------------------------------
/// A basic tag for a list of typenames. This struct can be subclassed
/// and still behave like a list tag.
#if defined(VTKM_HAVE_CXX_11)
template<typename... ArgTypes>
struct ListTagBase : detail::ListRoot
{
typedef detail::ListBase<void(ArgTypes...)> List;
};
#else
template<$template_params(max_base_list, default=' = vtkm::internal::NullType')>
struct ListTagBase : detail::ListRoot
{
typedef detail::ListBase<void($param_list(max_base_list))> List;
};
$for(num_params in xrange(0, (max_base_list+1)-1))\
template<$template_params(num_params)>
struct ListTagBase<$param_list(num_params)> : detail::ListRoot
{
typedef detail::ListBase<void($param_list(num_params))> List;
};
$endfor\
#endif
} // namespace vtkm
#endif //vtk_m_internal_ListTagDetail_h

2377
vtkm/internal/brigand.hpp Normal file

File diff suppressed because it is too large Load Diff

@ -136,11 +136,11 @@ void TryList(const vtkm::Vec<int,N> &expected, ListTag)
void TestLists()
{
std::cout << "Valid List Tag Checks" << std::endl;
VTKM_TEST_ASSERT(vtkm::internal::ListTagCheck<TestListTag1>::Valid,
VTKM_TEST_ASSERT(vtkm::internal::ListTagCheck<TestListTag1>::value,
"Failed list tag check");
VTKM_TEST_ASSERT(vtkm::internal::ListTagCheck<TestListTagJoin>::Valid,
VTKM_TEST_ASSERT(vtkm::internal::ListTagCheck<TestListTagJoin>::value,
"Failed list tag check");
VTKM_TEST_ASSERT(!vtkm::internal::ListTagCheck<TestClass<1> >::Valid,
VTKM_TEST_ASSERT(!vtkm::internal::ListTagCheck<TestClass<1> >::value,
"Failed list tag check");
std::cout << "ListTagEmpty" << std::endl;