VTK-m  1.8
ArrayHandleDecorator.h
Go to the documentation of this file.
1 //============================================================================
2 // Copyright (c) Kitware, Inc.
3 // All rights reserved.
4 // See LICENSE.txt for details.
5 //
6 // This software is distributed WITHOUT ANY WARRANTY; without even
7 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 // PURPOSE. See the above copyright notice for more information.
9 //============================================================================
10 #ifndef vtk_m_ArrayHandleDecorator_h
11 #define vtk_m_ArrayHandleDecorator_h
12 
13 #include <vtkm/cont/ArrayHandle.h>
14 #include <vtkm/cont/ErrorBadType.h>
15 #include <vtkm/cont/Storage.h>
16 
17 #include <vtkm/List.h>
18 #include <vtkm/StaticAssert.h>
19 #include <vtkm/Tuple.h>
20 #include <vtkm/VecTraits.h>
21 
23 
24 #include <vtkmstd/integer_sequence.h>
25 
26 
27 #include <type_traits>
28 #include <utility>
29 
30 namespace vtkm
31 {
32 namespace internal
33 {
34 
35 namespace decor
36 {
37 
38 // Generic InverseFunctor implementation that does nothing.
39 struct NoOpInverseFunctor
40 {
41  NoOpInverseFunctor() = default;
42  template <typename... Ts>
43  VTKM_EXEC_CONT NoOpInverseFunctor(Ts...)
44  {
45  }
46  template <typename VT>
47  VTKM_EXEC_CONT void operator()(vtkm::Id, VT) const
48  {
49  }
50 };
51 
52 } // namespace decor
53 
54 // The portal for ArrayHandleDecorator. Get calls FunctorType::operator(), and
55 // Set calls InverseFunctorType::operator(), but only if the DecoratorImpl
56 // provides an inverse.
57 template <typename ValueType_, typename FunctorType_, typename InverseFunctorType_>
58 class VTKM_ALWAYS_EXPORT ArrayPortalDecorator
59 {
60 public:
61  using ValueType = ValueType_;
62  using FunctorType = FunctorType_;
63  using InverseFunctorType = InverseFunctorType_;
64  using ReadOnly = std::is_same<InverseFunctorType, decor::NoOpInverseFunctor>;
65 
67  ArrayPortalDecorator() {}
68 
69  VTKM_CONT
70  ArrayPortalDecorator(FunctorType func, InverseFunctorType iFunc, vtkm::Id numValues)
71  : Functor(func)
72  , InverseFunctor(iFunc)
73  , NumberOfValues(numValues)
74  {
75  }
76 
78  vtkm::Id GetNumberOfValues() const { return this->NumberOfValues; }
79 
81  ValueType Get(vtkm::Id index) const { return this->Functor(index); }
82 
83  template <typename ReadOnly_ = ReadOnly,
84  typename = typename std::enable_if<!ReadOnly_::value>::type>
85  VTKM_EXEC_CONT void Set(vtkm::Id index, const ValueType& value) const
86  {
87  this->InverseFunctor(index, value);
88  }
89 
90 private:
91  FunctorType Functor;
92  InverseFunctorType InverseFunctor;
93  vtkm::Id NumberOfValues;
94 };
95 }
96 } // namespace vtkm::internal
97 
98 namespace vtkm
99 {
100 namespace cont
101 {
102 
103 namespace internal
104 {
105 
106 namespace decor
107 {
108 
109 // Ensures that all types in variadic container ArrayHandleList are subclasses
110 // of ArrayHandleBase.
111 template <typename ArrayHandleList>
113 
114 namespace detail
115 {
116 
117 // Tests whether DecoratorImplT has a CreateInverseFunctor(Portals...) method.
118 template <typename DecoratorImplT, typename PortalList>
119 struct IsFunctorInvertibleImpl;
120 
121 template <typename DecoratorImplT, template <typename...> class List, typename... PortalTs>
122 struct IsFunctorInvertibleImpl<DecoratorImplT, List<PortalTs...>>
123 {
124 private:
125  template <
126  typename T,
127  typename U = decltype(std::declval<T>().CreateInverseFunctor(std::declval<PortalTs&&>()...))>
128  static std::true_type InverseExistsTest(int);
129 
130  template <typename T>
131  static std::false_type InverseExistsTest(...);
132 
133 public:
134  using type = decltype(InverseExistsTest<DecoratorImplT>(0));
135 };
136 
137 // Tests whether DecoratorImplT has an AllocateSourceArrays(size, Arrays...) method.
138 template <typename DecoratorImplT, typename ArrayList>
139 struct IsDecoratorAllocatableImpl;
140 
141 template <typename DecoratorImplT, template <typename...> class List, typename... ArrayTs>
142 struct IsDecoratorAllocatableImpl<DecoratorImplT, List<ArrayTs...>>
143 {
144 private:
145  template <
146  typename T,
147  typename U = decltype(std::declval<T>().AllocateSourceArrays(0,
149  std::declval<vtkm::cont::Token&>(),
150  std::declval<ArrayTs&>()...))>
151  static std::true_type Exists(int);
152  template <typename T>
153  static std::false_type Exists(...);
154 
155 public:
156  using type = decltype(Exists<DecoratorImplT>(0));
157 };
158 
159 // Deduces the type returned by DecoratorImplT::CreateFunctor when given
160 // the specified portals.
161 template <typename DecoratorImplT, typename PortalList>
162 struct GetFunctorTypeImpl;
163 
164 template <typename DecoratorImplT, template <typename...> class List, typename... PortalTs>
165 struct GetFunctorTypeImpl<DecoratorImplT, List<PortalTs...>>
166 {
167  using type =
168  decltype(std::declval<DecoratorImplT>().CreateFunctor(std::declval<PortalTs&&>()...));
169 };
170 
171 // Deduces the type returned by DecoratorImplT::CreateInverseFunctor when given
172 // the specified portals. If DecoratorImplT doesn't have a CreateInverseFunctor
173 // method, a NoOp functor will be used instead.
174 template <typename CanWrite, typename DecoratorImplT, typename PortalList>
175 struct GetInverseFunctorTypeImpl;
176 
177 template <typename DecoratorImplT, template <typename...> class List, typename... PortalTs>
178 struct GetInverseFunctorTypeImpl<std::true_type, DecoratorImplT, List<PortalTs...>>
179 {
180  using type =
181  decltype(std::declval<DecoratorImplT>().CreateInverseFunctor(std::declval<PortalTs&&>()...));
182 };
183 
184 template <typename DecoratorImplT, typename PortalList>
185 struct GetInverseFunctorTypeImpl<std::false_type, DecoratorImplT, PortalList>
186 {
187  using type = vtkm::internal::decor::NoOpInverseFunctor;
188 };
189 
190 // Get appropriate portals from a source array.
191 // See note below about using non-writable portals in invertible functors.
192 // We need to sub in const portals when writable ones don't exist.
193 template <typename ArrayT>
194 typename std::decay<ArrayT>::type::WritePortalType GetWritePortalImpl(
195  std::true_type,
196  ArrayT&& array,
198  vtkm::cont::Token& token)
199 {
200  return ArrayT::StorageType::CreateWritePortal(array.GetBuffers(), device, token);
201 }
202 
203 template <typename ArrayT>
204 typename std::decay<ArrayT>::type::ReadPortalType GetWritePortalImpl(
205  std::false_type,
206  ArrayT&& array,
208  vtkm::cont::Token& token)
209 {
210  return ArrayT::StorageType::CreateReadPortal(array.GetBuffers(), device, token);
211 }
212 
213 } // namespace detail
214 
215 // Get portal types:
216 // We allow writing to an AHDecorator if *any* of the ArrayHandles are writable.
217 // This means we have to avoid calling PrepareForOutput, etc on non-writable
218 // array handles, since these may throw. On non-writable handles, use the
219 // const array handles so we can at least read from them in the inverse
220 // functors.
221 template <typename ArrayT>
222 using GetWritePortalType = std::conditional_t<
223  vtkm::internal::PortalSupportsSets<typename std::decay<ArrayT>::type::WritePortalType>::value,
224  typename std::decay<ArrayT>::type::WritePortalType,
225  typename std::decay<ArrayT>::type::ReadPortalType>;
226 
227 template <typename ArrayT>
228 using GetReadPortalType = typename std::decay<ArrayT>::type::ReadPortalType;
229 
230 // Get portal objects:
231 // See note above -- we swap in const portals sometimes.
232 template <typename ArrayT>
233 GetWritePortalType<typename std::decay<ArrayT>::type>
234 WritePortal(ArrayT&& array, vtkm::cont::DeviceAdapterId device, vtkm::cont::Token& token)
235 {
236  return detail::GetWritePortalImpl(
237  IsWritableArrayHandle<ArrayT>{}, std::forward<ArrayT>(array), device, token);
238 }
239 
240 template <typename ArrayT>
241 GetReadPortalType<typename std::decay<ArrayT>::type> ReadPortal(const ArrayT& array,
243  vtkm::cont::Token& token)
244 {
245  return ArrayT::StorageType::CreateReadPortal(array.GetBuffers(), device, token);
246 }
247 
248 // Equivalent to std::true_type if *any* portal in PortalList can be written to.
249 // If all are read-only, std::false_type is used instead.
250 template <typename PortalList>
252 
253 // Set to std::true_type if DecoratorImplT::CreateInverseFunctor can be called
254 // with the supplied portals, or std::false_type otherwise.
255 template <typename DecoratorImplT, typename PortalList>
256 using IsFunctorInvertible =
257  typename detail::IsFunctorInvertibleImpl<DecoratorImplT, PortalList>::type;
258 
259 // Set to std::true_type if DecoratorImplT::AllocateSourceArrays can be called
260 // with the supplied arrays, or std::false_type otherwise.
261 template <typename DecoratorImplT, typename ArrayList>
262 using IsDecoratorAllocatable =
263  typename detail::IsDecoratorAllocatableImpl<DecoratorImplT, ArrayList>::type;
264 
265 // std::true_type/std::false_type depending on whether the decorator impl has a
266 // CreateInversePortal method AND any of the arrays are writable.
267 template <typename DecoratorImplT, typename PortalList>
268 using CanWriteToFunctor = vtkm::internal::meta::And<IsFunctorInvertible<DecoratorImplT, PortalList>,
269  AnyPortalIsWritable<PortalList>>;
270 
271 // The FunctorType for the provided implementation and portal types.
272 template <typename DecoratorImplT, typename PortalList>
273 using GetFunctorType = typename detail::GetFunctorTypeImpl<DecoratorImplT, PortalList>::type;
274 
275 // The InverseFunctorType for the provided implementation and portal types.
276 // Will detect when inversion is not possible and return a NoOp functor instead.
277 template <typename DecoratorImplT, typename PortalList>
278 using GetInverseFunctorType =
279  typename detail::GetInverseFunctorTypeImpl<CanWriteToFunctor<DecoratorImplT, PortalList>,
280  DecoratorImplT,
281  PortalList>::type;
282 
283 // Convert a sequence of array handle types to a list of portals:
284 
285 // Some notes on this implementation:
286 // - A more straightforward way to implement these to types would be to take
287 // a simple template that takes a vtkm::List of array types and convert
288 // that with vtkm::ListTransform<ArrayList, GetWritePortalType>. However,
289 // this causes a strange compiler error in VS 2017 when evaluating the
290 // `ValueType` in `DecoratorStorageTraits`. (It does not recognize the
291 // decorator impl functor as a function taking one argument, even when it
292 // effectively is.) A previous similar implementation caused an ICE in
293 // VS 2015 (although that compiler is no longer supported anyway).
294 // - The same problem happens with VS 2017 if you just try to create a list
295 // with vtkm::List<GetWritePortalType<ArrayTs>...>.
296 // - So we jump through some decltype/declval hoops here to get this to work:
297 template <typename... ArrayTs>
298 using GetReadPortalList =
300  std::declval<vtkm::cont::DeviceAdapterId>(),
301  std::declval<vtkm::cont::Token&>())))...>;
302 
303 template <typename... ArrayTs>
304 using GetWritePortalList =
306  std::declval<vtkm::cont::DeviceAdapterId>(),
307  std::declval<vtkm::cont::Token&>())))...>;
308 
309 template <vtkm::IdComponent I, typename ArrayTupleType>
310 struct BufferIndexImpl
311 {
312  static constexpr vtkm::IdComponent Value()
313  {
314  return BufferIndexImpl<I - 1, ArrayTupleType>::Value() +
316  }
317 };
318 template <typename ArrayTupleType>
319 struct BufferIndexImpl<0, ArrayTupleType>
320 {
321  static constexpr vtkm::IdComponent Value()
322  {
323  // One buffer reserved for metadata.
324  return 1;
325  }
326 };
327 
328 template <typename DecoratorImplT>
329 struct DecoratorMetaData
330 {
331  DecoratorImplT Implementation;
332  vtkm::Id NumberOfValues = 0;
333 
334  DecoratorMetaData(const DecoratorImplT& implementation, vtkm::Id numValues)
335  : Implementation(implementation)
336  , NumberOfValues(numValues)
337  {
338  }
339 
340  DecoratorMetaData() = default;
341 };
342 
343 template <typename DecoratorImplT, typename... ArrayTs>
344 struct DecoratorStorageTraits
345 {
346  using ArrayList = vtkm::List<ArrayTs...>;
347 
348  VTKM_STATIC_ASSERT_MSG(sizeof...(ArrayTs) > 0,
349  "Must specify at least one source array handle for "
350  "ArrayHandleDecorator. Consider using "
351  "ArrayHandleImplicit instead.");
352 
353  // Need to check this here, since this traits struct is used in the
354  // ArrayHandleDecorator superclass definition before any other
355  // static_asserts could be used.
356  VTKM_STATIC_ASSERT_MSG(decor::AllAreArrayHandles<ArrayList>::value,
357  "Trailing template parameters for "
358  "ArrayHandleDecorator must be a list of ArrayHandle "
359  "types.");
360 
361  using ArrayTupleType = vtkm::Tuple<ArrayTs...>;
362 
363  // size_t integral constants that index ArrayTs:
364  using IndexList = vtkmstd::make_index_sequence<sizeof...(ArrayTs)>;
365 
366  // Returns the index into the buffers array for the array at the given index.
367  template <vtkm::IdComponent I>
368  static constexpr vtkm::IdComponent BufferIndex()
369  {
370  return BufferIndexImpl<I, ArrayTupleType>::Value();
371  }
372 
373  // Converts a buffers array to the ArrayHandle at the given index.
374  template <vtkm::IdComponent I>
375  static vtkm::TupleElement<I, ArrayTupleType> BuffersToArray(
376  const vtkm::cont::internal::Buffer* buffers)
377  {
378  return vtkm::TupleElement<I, ArrayTupleType>(buffers + BufferIndex<I>());
379  }
380 
381  using MetaData = DecoratorMetaData<DecoratorImplT>;
382 
383  static MetaData& GetMetaData(const vtkm::cont::internal::Buffer* buffers)
384  {
385  return buffers[0].GetMetaData<MetaData>();
386  }
387 
388  // true_type/false_type depending on whether the decorator supports Allocate:
389  using IsAllocatable = IsDecoratorAllocatable<DecoratorImplT, ArrayList>;
390 
391  // Portal lists:
392  // NOTE we have to pass the parameter pack here instead of using ArrayList
393  // with vtkm::ListTransform, since that's causing problems with VS 2017:
394  using WritePortalList = GetWritePortalList<ArrayTs...>;
395  using ReadPortalList = GetReadPortalList<ArrayTs...>;
396 
397  // Functors:
398  using WriteFunctorType = GetFunctorType<DecoratorImplT, WritePortalList>;
399  using ReadFunctorType = GetFunctorType<DecoratorImplT, ReadPortalList>;
400 
401  // Inverse functors:
402  using InverseWriteFunctorType = GetInverseFunctorType<DecoratorImplT, WritePortalList>;
403 
404  using InverseReadFunctorType = vtkm::internal::decor::NoOpInverseFunctor;
405 
406  // Misc:
407  // ValueType is derived from DecoratorImplT::CreateFunctor(...)'s operator().
408  using ValueType = decltype(std::declval<WriteFunctorType>()(0));
409 
410  // Decorator portals:
411  using WritePortalType =
412  vtkm::internal::ArrayPortalDecorator<ValueType, WriteFunctorType, InverseWriteFunctorType>;
413 
414  using ReadPortalType =
415  vtkm::internal::ArrayPortalDecorator<ValueType, ReadFunctorType, InverseReadFunctorType>;
416 
417  // helper for constructing portals with the appropriate functors. This is
418  // where we decide whether or not to call `CreateInverseFunctor` on the
419  // implementation class.
420  // Do not use these directly, they are helpers for the MakePortal[...]
421  // methods below.
422  template <typename DecoratorPortalType, typename... PortalTs>
423  VTKM_CONT static
424  typename std::enable_if<DecoratorPortalType::ReadOnly::value, DecoratorPortalType>::type
425  CreatePortalDecorator(vtkm::Id numVals, const DecoratorImplT& impl, PortalTs&&... portals)
426  { // Portal is read only:
427  return { impl.CreateFunctor(std::forward<PortalTs>(portals)...),
428  typename DecoratorPortalType::InverseFunctorType{},
429  numVals };
430  }
431 
432  template <typename DecoratorPortalType, typename... PortalTs>
433  VTKM_CONT static
434  typename std::enable_if<!DecoratorPortalType::ReadOnly::value, DecoratorPortalType>::type
435  CreatePortalDecorator(vtkm::Id numVals, const DecoratorImplT& impl, PortalTs... portals)
436  { // Portal is read/write:
437  return { impl.CreateFunctor(portals...), impl.CreateInverseFunctor(portals...), numVals };
438  }
439 
440  // Static dispatch for calling AllocateSourceArrays on supported implementations:
441  VTKM_CONT [[noreturn]] static void CallAllocate(std::false_type,
442  vtkm::Id,
443  vtkm::cont::internal::Buffer*,
446  ArrayTs...)
447  {
448  throw vtkm::cont::ErrorBadType("Allocate not supported by this ArrayHandleDecorator.");
449  }
450 
451  VTKM_CONT static void CallAllocate(std::true_type,
452  vtkm::Id newSize,
453  vtkm::cont::internal::Buffer* buffers,
454  vtkm::CopyFlag preserve,
455  vtkm::cont::Token& token,
456  ArrayTs... arrays)
457  {
458  MetaData& metadata = GetMetaData(buffers);
459  metadata.Implementation.AllocateSourceArrays(newSize, preserve, token, arrays...);
460  metadata.NumberOfValues = newSize;
461  }
462 
463 
464  // Portal construction methods. These actually create portals.
465  template <std::size_t... Indices>
466  VTKM_CONT static WritePortalType CreateWritePortal(const vtkm::cont::internal::Buffer* buffers,
467  vtkm::Id numValues,
468  vtkmstd::index_sequence<Indices...>,
470  vtkm::cont::Token& token)
471  {
472  return CreatePortalDecorator<WritePortalType>(
473  numValues,
474  GetMetaData(buffers).Implementation,
475  WritePortal(BuffersToArray<Indices>(buffers), device, token)...);
476  }
477 
478  template <std::size_t... Indices>
479  VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
480  vtkm::Id numValues,
481  vtkmstd::index_sequence<Indices...>,
483  vtkm::cont::Token& token)
484  {
485  return CreatePortalDecorator<ReadPortalType>(
486  numValues,
487  GetMetaData(buffers).Implementation,
488  ReadPortal(BuffersToArray<Indices>(buffers), device, token)...);
489  }
490 
491  template <std::size_t... Indices>
492  VTKM_CONT static void AllocateSourceArrays(vtkm::Id numValues,
493  vtkm::cont::internal::Buffer* buffers,
494  vtkm::CopyFlag preserve,
495  vtkm::cont::Token& token,
496  vtkmstd::index_sequence<Indices...>)
497  {
498  CallAllocate(
499  IsAllocatable{}, numValues, buffers, preserve, token, BuffersToArray<Indices>(buffers)...);
500  }
501 };
502 
503 } // end namespace decor
504 
505 template <typename DecoratorImplT, typename... ArrayTs>
506 struct VTKM_ALWAYS_EXPORT StorageTagDecorator
507 {
508 };
509 
510 template <typename DecoratorImplT, typename... ArrayTs>
511 class Storage<typename decor::DecoratorStorageTraits<DecoratorImplT, ArrayTs...>::ValueType,
512  StorageTagDecorator<DecoratorImplT, ArrayTs...>>
513 {
514  using Traits = decor::DecoratorStorageTraits<DecoratorImplT, ArrayTs...>;
515  using IndexList = typename Traits::IndexList;
516  using MetaData = typename Traits::MetaData;
517 
518 public:
519  using ReadPortalType = typename Traits::ReadPortalType;
520  using WritePortalType = typename Traits::WritePortalType;
521 
522  VTKM_CONT constexpr static vtkm::IdComponent GetNumberOfBuffers()
523  {
524  return Traits::template BufferIndex<static_cast<vtkm::IdComponent>(sizeof...(ArrayTs))>();
525  }
526 
527  VTKM_CONT static vtkm::Id GetNumberOfValues(const vtkm::cont::internal::Buffer* buffers)
528  {
529  return Traits::GetMetaData(buffers).NumberOfValues;
530  }
531 
532  VTKM_CONT static void ResizeBuffers(vtkm::Id numValues,
533  vtkm::cont::internal::Buffer* buffers,
534  vtkm::CopyFlag preserve,
535  vtkm::cont::Token& token)
536  {
537  if (numValues != GetNumberOfValues(buffers))
538  {
539  Traits::AllocateSourceArrays(numValues, buffers, preserve, token, IndexList{});
540  }
541  else
542  {
543  // Do nothing. We have this condition to allow allocating the same size when the
544  // array cannot be resized.
545  }
546  }
547 
548  VTKM_CONT static ReadPortalType CreateReadPortal(const vtkm::cont::internal::Buffer* buffers,
550  vtkm::cont::Token& token)
551  {
552  return Traits::CreateReadPortal(
553  buffers, GetNumberOfValues(buffers), IndexList{}, device, token);
554  }
555 
556  VTKM_CONT static WritePortalType CreateWritePortal(vtkm::cont::internal::Buffer* buffers,
558  vtkm::cont::Token& token)
559  {
560  return Traits::CreateWritePortal(
561  buffers, GetNumberOfValues(buffers), IndexList{}, device, token);
562  }
563 
564  VTKM_CONT static std::vector<vtkm::cont::internal::Buffer>
565  CreateBuffers(const DecoratorImplT& implementation, vtkm::Id numValues, const ArrayTs&... arrays)
566  {
567  return vtkm::cont::internal::CreateBuffers(MetaData(implementation, numValues), arrays...);
568  }
569 };
570 
571 template <typename DecoratorImplT, typename... ArrayTs>
572 struct DecoratorHandleTraits
573 {
574  using StorageTraits = decor::DecoratorStorageTraits<DecoratorImplT, ArrayTs...>;
575  using ValueType = typename StorageTraits::ValueType;
576  using StorageTag = StorageTagDecorator<DecoratorImplT, ArrayTs...>;
577  using StorageType = vtkm::cont::internal::Storage<ValueType, StorageTag>;
579 };
580 
581 } // namespace internal
582 
655 template <typename DecoratorImplT, typename... ArrayTs>
657  : public internal::DecoratorHandleTraits<typename std::decay<DecoratorImplT>::type,
658  typename std::decay<ArrayTs>::type...>::Superclass
659 {
660 private:
661  using Traits = internal::DecoratorHandleTraits<typename std::decay<DecoratorImplT>::type,
662  typename std::decay<ArrayTs>::type...>;
663  using StorageType = typename Traits::StorageType;
664 
665 public:
667  (ArrayHandleDecorator<typename std::decay<DecoratorImplT>::type,
668  typename std::decay<ArrayTs>::type...>),
669  (typename Traits::Superclass));
670 
671  VTKM_CONT
673  const typename std::decay<DecoratorImplT>::type& impl,
674  const typename std::decay<ArrayTs>::type&... arrays)
675  : Superclass{ StorageType::CreateBuffers(impl, numValues, arrays...) }
676  {
677  }
678 };
679 
683 template <typename DecoratorImplT, typename... ArrayTs>
684 VTKM_CONT ArrayHandleDecorator<typename std::decay<DecoratorImplT>::type,
685  typename std::decay<ArrayTs>::type...>
686 make_ArrayHandleDecorator(vtkm::Id numValues, DecoratorImplT&& f, ArrayTs&&... arrays)
687 {
689  VTKM_STATIC_ASSERT_MSG(sizeof...(ArrayTs) > 0,
690  "Must specify at least one source array handle for "
691  "ArrayHandleDecorator. Consider using "
692  "ArrayHandleImplicit instead.");
693  VTKM_STATIC_ASSERT_MSG(internal::decor::AllAreArrayHandles<AHList>::value,
694  "Trailing template parameters for "
695  "ArrayHandleDecorator must be a list of ArrayHandle "
696  "types.");
697 
698  return { numValues, std::forward<DecoratorImplT>(f), std::forward<ArrayTs>(arrays)... };
699 }
700 }
701 } // namespace vtkm::cont
702 
703 #ifdef VTKM_USE_TAO_SEQ
704 #undef VTKM_USE_TAO_SEQ
705 #endif
706 
707 #endif //vtk_m_ArrayHandleDecorator_h
vtkm::cont::ArrayHandle
Manages an array-worth of data.
Definition: ArrayHandle.h:287
ArrayHandle.h
vtkm::TupleElement
typename detail::TupleElementImpl< Index, TupleType >::type TupleElement
Becomes the type of the given index for the given vtkm::Tuple.
Definition: Tuple.h:63
vtkm
VTKM_NO_DEPRECATED_VIRTUAL.
Definition: Algorithms.h:18
ArrayPortalHelpers.h
VTKM_EXEC_CONT
#define VTKM_EXEC_CONT
Definition: ExportMacros.h:52
vtkm::Get
VTKM_SUPPRESS_EXEC_WARNINGS VTKM_EXEC_CONT auto Get(const vtkm::Tuple< Ts... > &tuple) -> decltype(tuple.template Get< Index >())
Retrieve the object from a vtkm::Tuple at the given index.
Definition: Tuple.h:83
vtkm::IdComponent
vtkm::Int32 IdComponent
Represents a component ID (index of component in a vector).
Definition: Types.h:168
Storage.h
vtkm::cont::ErrorBadType
This class is thrown when VTK-m encounters data of a type that is incompatible with the current opera...
Definition: ErrorBadType.h:25
vtkm::cont::make_ArrayHandleDecorator
VTKM_CONT ArrayHandleDecorator< typename std::decay< DecoratorImplT >::type, typename std::decay< ArrayTs >::type... > make_ArrayHandleDecorator(vtkm::Id numValues, DecoratorImplT &&f, ArrayTs &&... arrays)
Create an ArrayHandleDecorator with the specified number of values that uses the provided DecoratorIm...
Definition: ArrayHandleDecorator.h:686
vtkm::Id
vtkm::Int32 Id
Represents an ID (index into arrays).
Definition: Types.h:191
vtkm::cont::Token
A token to hold the scope of an ArrayHandle or other object.
Definition: Token.h:35
VTKM_STATIC_ASSERT_MSG
#define VTKM_STATIC_ASSERT_MSG(condition, message)
Definition: StaticAssert.h:18
VTKM_CONT
#define VTKM_CONT
Definition: ExportMacros.h:57
vtkm::cont::ArrayHandleDecorator::ArrayHandleDecorator
VTKM_CONT ArrayHandleDecorator(vtkm::Id numValues, const typename std::decay< DecoratorImplT >::type &impl, const typename std::decay< ArrayTs >::type &... arrays)
Definition: ArrayHandleDecorator.h:672
vtkm::cont::DeviceAdapterId
Definition: DeviceAdapterTag.h:52
vtkm::CopyFlag::Off
@ Off
vtkm::cont::ArrayHandleDecorator::VTKM_ARRAY_HANDLE_SUBCLASS
VTKM_ARRAY_HANDLE_SUBCLASS(ArrayHandleDecorator,(ArrayHandleDecorator< typename std::decay< DecoratorImplT >::type, typename std::decay< ArrayTs >::type... >),(typename Traits::Superclass))
vtkm::Tuple
VTK-m replacement for std::tuple.
Definition: Tuple.h:35
StaticAssert.h
vtkm::cont::ArrayHandle::StorageType
vtkm::cont::internal::Storage< ValueType, StorageTag > StorageType
Definition: ArrayHandle.h:296
vtkm::List
Definition: List.h:32
vtkm::CopyFlag
CopyFlag
Definition: Flags.h:16
vtkm::cont::ArrayHandleDecorator::Traits
internal::DecoratorHandleTraits< typename std::decay< DecoratorImplT >::type, typename std::decay< ArrayTs >::type... > Traits
Definition: ArrayHandleDecorator.h:662
VTKM_ALWAYS_EXPORT
#define VTKM_ALWAYS_EXPORT
Definition: ExportMacros.h:92
ErrorBadType.h
vtkm::ListAll
vtkm::ListReduce< vtkm::ListTransform< List, Predicate >, vtkm::internal::meta::And, std::true_type > ListAll
Determines whether all the types in the list are "true.".
Definition: List.h:890
vtkm::ListAny
vtkm::ListReduce< vtkm::ListTransform< List, Predicate >, vtkm::internal::meta::Or, std::false_type > ListAny
Determines whether any of the types in the list are "true.".
Definition: List.h:915
vtkm::cont::ArrayHandleDecorator
A fancy ArrayHandle that can be used to modify the results from one or more source ArrayHandle.
Definition: ArrayHandleDecorator.h:656
Tuple.h
VecTraits.h
List.h