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