1 //============================================================================ 2 // Copyright (c) Kitware, Inc. 3 // All rights reserved. 4 // See LICENSE.txt for details. 5 // This software is distributed WITHOUT ANY WARRANTY; without even 6 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 7 // PURPOSE. See the above copyright notice for more information. 8 // 9 // Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS). 10 // Copyright 2014 UT-Battelle, LLC. 11 // Copyright 2014 Los Alamos National Security. 12 // 13 // Under the terms of Contract DE-NA0003525 with NTESS, 14 // the U.S. Government retains certain rights in this software. 15 // 16 // Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National 17 // Laboratory (LANL), the U.S. Government retains certain rights in 18 // this software. 19 //============================================================================ 20 21 #ifndef vtk_m_internal_ListTagDetail_h 22 #define vtk_m_internal_ListTagDetail_h 23 24 #if !defined(vtk_m_ListTag_h) && !defined(VTKM_TEST_HEADER_BUILD) 25 #error ListTagDetail.h must be included from ListTag.h 26 #endif 27 28 #include <vtkm/Types.h> 29 #include <vtkm/internal/brigand.hpp> 30 31 namespace vtkm 32 { 33 namespace detail 34 { 35 36 //----------------------------------------------------------------------------- 37 38 /// Base class that all ListTag classes inherit from. Helps identify lists 39 /// in macros like VTKM_IS_LIST_TAG. 40 /// 41 struct ListRoot 42 { 43 }; 44 45 template <class... T> 46 using ListBase = brigand::list<T...>; 47 48 /// list value that is used to represent a list actually matches all values 49 struct UniversalTag 50 { 51 //We never want this tag constructed, and by deleting the constructor 52 //we get an error when trying to use this class with ForEach. 53 UniversalTag() = delete; 54 }; 55 56 //----------------------------------------------------------------------------- 57 template <typename ListTag1, typename ListTag2> 58 struct ListJoin 59 { 60 using type = brigand::append<ListTag1, ListTag2>; 61 }; 62 63 template <typename ListTag> 64 struct ListJoin<vtkm::detail::ListBase<vtkm::detail::UniversalTag>, ListTag> 65 { 66 using type = vtkm::detail::ListBase<vtkm::detail::UniversalTag>; 67 }; 68 69 template <typename ListTag> 70 struct ListJoin<ListTag, vtkm::detail::ListBase<vtkm::detail::UniversalTag>> 71 { 72 using type = vtkm::detail::ListBase<vtkm::detail::UniversalTag>; 73 }; 74 75 //----------------------------------------------------------------------------- 76 template <typename Type, typename List> 77 struct ListContainsImpl; 78 79 //----------------------------------------------------------------------------- 80 template <typename Type> 81 struct ListContainsImpl<Type, brigand::empty_sequence> 82 { 83 static constexpr bool value = false; 84 }; 85 86 //----------------------------------------------------------------------------- 87 template <typename Type> 88 struct ListContainsImpl<Type, brigand::list<vtkm::detail::UniversalTag>> 89 { 90 static constexpr bool value = true; 91 }; 92 93 //----------------------------------------------------------------------------- 94 template <typename Type, typename T1> 95 struct ListContainsImpl<Type, brigand::list<T1>> 96 { 97 static constexpr bool value = std::is_same<Type, T1>::value; 98 }; 99 100 //----------------------------------------------------------------------------- 101 template <typename Type, typename T1, typename T2> 102 struct ListContainsImpl<Type, brigand::list<T1, T2>> 103 { 104 static constexpr bool value = std::is_same<Type, T1>::value || std::is_same<Type, T2>::value; 105 }; 106 107 //----------------------------------------------------------------------------- 108 template <typename Type, typename T1, typename T2, typename T3> 109 struct ListContainsImpl<Type, brigand::list<T1, T2, T3>> 110 { 111 static constexpr bool value = 112 std::is_same<Type, T1>::value || std::is_same<Type, T2>::value || std::is_same<Type, T3>::value; 113 }; 114 115 //----------------------------------------------------------------------------- 116 template <typename Type, typename T1, typename T2, typename T3, typename T4> 117 struct ListContainsImpl<Type, brigand::list<T1, T2, T3, T4>> 118 { 119 static constexpr bool value = std::is_same<Type, T1>::value || std::is_same<Type, T2>::value || 120 std::is_same<Type, T3>::value || std::is_same<Type, T4>::value; 121 }; 122 123 //----------------------------------------------------------------------------- 124 template <typename Type, typename List> 125 struct ListContainsImpl 126 { 127 using find_result = brigand::find<List, std::is_same<brigand::_1, Type>>; 128 using size = brigand::size<find_result>; 129 static constexpr bool value = (size::value != 0); 130 }; 131 132 //----------------------------------------------------------------------------- 133 template <class T, class U, class ListTag> 134 struct intersect_tags 135 { 136 using has_u = ListContainsImpl<U, ListTag>; 137 using type = typename std::conditional<has_u::value, brigand::push_back<T, U>, T>::type; 138 }; 139 140 //----------------------------------------------------------------------------- 141 template <typename ListTag1, typename ListTag2> 142 struct ListIntersect 143 { 144 using type = 145 brigand::fold<ListTag1, 146 brigand::list<>, 147 intersect_tags<brigand::_state, brigand::_element, brigand::pin<ListTag2>>>; 148 }; 149 150 template <typename ListTag> 151 struct ListIntersect<vtkm::detail::ListBase<vtkm::detail::UniversalTag>, ListTag> 152 { 153 using type = ListTag; 154 }; 155 156 template <typename ListTag> 157 struct ListIntersect<ListTag, vtkm::detail::ListBase<vtkm::detail::UniversalTag>> 158 { 159 using type = ListTag; 160 }; 161 162 template <typename SameListTag> 163 struct ListIntersect<SameListTag, SameListTag> 164 { 165 using type = SameListTag; 166 }; 167 168 template <typename Functor, typename... Args> 169 VTKM_CONT void ListForEachImpl(Functor&&, brigand::list<>, Args&&...) 170 { 171 } 172 173 template <typename Functor, typename T1, typename... Args> 174 VTKM_CONT void ListForEachImpl(Functor&& f, brigand::list<T1>, Args&&... args) 175 { 176 f(T1{}, std::forward<Args>(args)...); 177 } 178 179 template <typename Functor, typename T1, typename T2, typename... Args> 180 VTKM_CONT void ListForEachImpl(Functor&& f, brigand::list<T1, T2>, Args&&... args) 181 { 182 f(T1{}, std::forward<Args>(args)...); 183 f(T2{}, std::forward<Args>(args)...); 184 } 185 186 template <typename Functor, typename T1, typename T2, typename T3, typename... Args> 187 VTKM_CONT void ListForEachImpl(Functor&& f, brigand::list<T1, T2, T3>, Args&&... args) 188 { 189 f(T1{}, std::forward<Args>(args)...); 190 f(T2{}, std::forward<Args>(args)...); 191 f(T3{}, std::forward<Args>(args)...); 192 } 193 194 template <typename Functor, 195 typename T1, 196 typename T2, 197 typename T3, 198 typename T4, 199 typename... ArgTypes, 200 typename... Args> 201 VTKM_CONT void ListForEachImpl(Functor&& f, 202 brigand::list<T1, T2, T3, T4, ArgTypes...>&&, 203 Args&&... args) 204 { 205 f(T1{}, std::forward<Args>(args)...); 206 f(T2{}, std::forward<Args>(args)...); 207 f(T3{}, std::forward<Args>(args)...); 208 f(T4{}, std::forward<Args>(args)...); 209 ListForEachImpl( 210 std::forward<Functor>(f), brigand::list<ArgTypes...>{}, std::forward<Args>(args)...); 211 } 212 213 template <typename R1, typename R2> 214 struct ListCrossProductImpl 215 { 216 // This is a lazy Cartesian product generator. 217 // This version was settled on as being the best default 218 // version as all compilers including Intel handle this 219 // implementation without issue for very large cross products 220 using type = brigand::reverse_fold< 221 brigand::list<R1, R2>, 222 brigand::list<brigand::list<>>, 223 brigand::lazy::join<brigand::lazy::transform< 224 brigand::_2, 225 brigand::defer<brigand::lazy::join<brigand::lazy::transform< 226 brigand::parent<brigand::_1>, 227 brigand::defer<brigand::bind< 228 brigand::list, 229 brigand::lazy::push_front<brigand::_1, brigand::parent<brigand::_1>>>>>>>>>>; 230 }; 231 232 //----------------------------------------------------------------------------- 233 template <typename List, typename Type> 234 struct ListAppendUniqueImpl 235 { 236 using type = typename std::conditional<ListContainsImpl<Type, List>::value, 237 List, 238 typename ListJoin<List, ListBase<Type>>::type>::type; 239 }; 240 241 } // namespace detail 242 243 //----------------------------------------------------------------------------- 244 /// A basic tag for a list of typenames. This struct can be subclassed 245 /// and still behave like a list tag. 246 template <typename... ArgTypes> 247 struct ListTagBase : detail::ListRoot 248 { 249 using list = detail::ListBase<ArgTypes...>; 250 }; 251 } 252 253 #endif //vtk_m_internal_ListTagDetail_h 254