//============================================================================
//  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.
//============================================================================
// **** DO NOT EDIT THIS FILE!!! ****
// This file is automatically generated by Tuple.h.in

#ifndef vtk_m_Tuple_h
#define vtk_m_Tuple_h

#include <vtkm/Types.h>

#include <vtkm/internal/DecayHelpers.h>
#include <vtkm/internal/IndexTag.h>



namespace vtkm
{

///@{
/// \brief VTK-m replacement for std::tuple
///
/// This function serves the same function as `std::tuple` and behaves similarly. However, this
/// version of `Tuple` works on devices that VTK-m supports. There are also some implementation
/// details that makes compiling faster for VTK-m use. We also provide some methods like `Apply`
/// and `ForEach` that are helpful for several VTK-m operations.
///
template <typename... Ts>
class Tuple;

/// \brief Get the size of a tuple.
///
/// Given a `vtkm::Tuple` type, because a `std::integral_constant` of the type.
///
template <typename TupleType>
using TupleSize = std::integral_constant<vtkm::IdComponent, TupleType::Size>;

/// \brief Compatible with `std::tuple_size` for `vtkm::Tuple`.
///
template <typename TupleType>
using tuple_size = std::integral_constant<std::size_t, static_cast<std::size_t>(TupleType::Size)>;

namespace detail
{

template <vtkm::IdComponent Index, typename TupleType>
struct TupleElementImpl
{
  using type = decltype(TupleType::ElementTypeI(vtkm::internal::IndexTag<Index>{}));
};

} // namespace detail

/// \brief Becomes the type of the given index for the given `vtkm::Tuple`.
///
template <vtkm::IdComponent Index, typename TupleType>
using TupleElement = typename detail::TupleElementImpl<Index, TupleType>::type;

/// \brief Compatible with `std::tuple_element` for `vtkm::Tuple`.
///
template <std::size_t Index, typename TupleType>
struct tuple_element
{
  using type = TupleElement<static_cast<vtkm::IdComponent>(Index), TupleType>;
};

/// \brief Compatible with `std::tuple_element_t` for `vtkm::Tuple`.
///
template <std::size_t Index, typename TupleType>
using tuple_element_t = typename tuple_element<Index, TupleType>::type;

///@{
/// \brief Retrieve the object from a `vtkm::Tuple` at the given index.
///
VTKM_SUPPRESS_EXEC_WARNINGS
template <vtkm::IdComponent Index, typename... Ts>
VTKM_EXEC_CONT auto Get(const vtkm::Tuple<Ts...>& tuple) -> decltype(tuple.template Get<Index>())
{
  return tuple.template Get<Index>();
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <vtkm::IdComponent Index, typename... Ts>
VTKM_EXEC_CONT auto Get(vtkm::Tuple<Ts...>& tuple) -> decltype(tuple.template Get<Index>())
{
  return tuple.template Get<Index>();
}
///@}

///@{
/// \brief Compatible with `std::get` for `vtkm::Tuple`.
///
VTKM_SUPPRESS_EXEC_WARNINGS
template <std::size_t Index, typename... Ts>
VTKM_EXEC_CONT auto get(const vtkm::Tuple<Ts...>& tuple)
  -> decltype(vtkm::Get<static_cast<vtkm::IdComponent>(Index)>(tuple))
{
  return vtkm::Get<static_cast<vtkm::IdComponent>(Index)>(tuple);
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <std::size_t Index, typename... Ts>
VTKM_EXEC_CONT auto get(vtkm::Tuple<Ts...>& tuple)
  -> decltype(vtkm::Get<static_cast<vtkm::IdComponent>(Index)>(tuple))
{
  return vtkm::Get<static_cast<vtkm::IdComponent>(Index)>(tuple);
}
///@}

/// \brief Creates a new `vtkm::Tuple` with the given types.
///
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename... Ts>
VTKM_EXEC_CONT auto MakeTuple(Ts&&... args) -> vtkm::Tuple<typename std::decay<Ts>::type...>
{
  return vtkm::Tuple<typename std::decay<Ts>::type...>(std::forward<Ts>(args)...);
}

/// \brief Compatible with `std::make_tuple` for `vtkm::Tuple`.
///
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename... Ts>
VTKM_EXEC_CONT auto make_tuple(Ts&&... args) -> decltype(vtkm::MakeTuple(std::forward<Ts>(args)...))
{
  return vtkm::MakeTuple(std::forward<Ts>(args)...);
}

namespace detail
{
struct TupleTransformFunctor
{
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Ts>
  VTKM_EXEC_CONT auto operator()(Function&& f, Ts&&... args)
    -> decltype(vtkm::MakeTuple(f(std::forward<Ts>(args))...))
  {
    return vtkm::MakeTuple(f(std::forward<Ts>(args))...);
  }
};

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename TupleType, typename Function>
VTKM_EXEC_CONT auto TupleTransform(TupleType&& tuple, Function&& f)
  -> decltype(tuple.Apply(TupleTransformFunctor{}, std::forward<Function>(f)))
{
  return tuple.Apply(TupleTransformFunctor{}, std::forward<Function>(f));
}

struct TupleForEachFunctor
{
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Ts>
  VTKM_EXEC_CONT void operator()(Function&& f, Ts&&... args)
  {
    (void)std::initializer_list<bool>{ (f(std::forward<Ts>(args)), false)... };
  }
};

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename TupleType, typename Function>
VTKM_EXEC_CONT auto TupleForEach(TupleType&& tuple, Function&& f)
  -> decltype(tuple.Apply(TupleForEachFunctor{}, std::forward<Function>(f)))
{
  return tuple.Apply(TupleForEachFunctor{}, std::forward<Function>(f));
}

} // namespace detail

template <>
class Tuple<>
{
public:
  static constexpr vtkm::IdComponent Size = 0;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)...))
  {
    return f(std::forward<Args>(args)...);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)...))
  {
    return f(std::forward<Args>(args)...);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&&) const
  {
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT vtkm::Tuple<> Transform(Function&&) const
  {
    return vtkm::Tuple<>{};
  }
};

// clang-format off

template<typename T0>
class Tuple<T0>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 1;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0>
  VTKM_EXEC_CONT Tuple(A0&& a0)
    : Value0(std::forward<A0>(a0))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0))
  {
    return f(std::forward<Args>(args)..., Value0);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0))
  {
    return f(std::forward<Args>(args)..., Value0);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1>
class Tuple<T0, T1>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 2;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1))
  {
    return f(std::forward<Args>(args)..., Value0, Value1);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1))
  {
    return f(std::forward<Args>(args)..., Value0, Value1);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1, typename T2>
class Tuple<T0, T1, T2>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 3;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1, typename T2, typename T3>
class Tuple<T0, T1, T2, T3>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }

  T3 Value3;
  static T3 ElementTypeI(vtkm::internal::IndexTag<3>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>)
  {
    return this->Value3;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>) const
  {
    return this->Value3;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 4;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2, T3>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2, A3&& a3)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
    , Value3(std::forward<A3>(a3))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1, typename T2, typename T3, typename T4>
class Tuple<T0, T1, T2, T3, T4>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }

  T3 Value3;
  static T3 ElementTypeI(vtkm::internal::IndexTag<3>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>)
  {
    return this->Value3;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>) const
  {
    return this->Value3;
  }

  T4 Value4;
  static T4 ElementTypeI(vtkm::internal::IndexTag<4>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>)
  {
    return this->Value4;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>) const
  {
    return this->Value4;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 5;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2, T3, T4>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
    , Value3(std::forward<A3>(a3))
    , Value4(std::forward<A4>(a4))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
class Tuple<T0, T1, T2, T3, T4, T5>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }

  T3 Value3;
  static T3 ElementTypeI(vtkm::internal::IndexTag<3>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>)
  {
    return this->Value3;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>) const
  {
    return this->Value3;
  }

  T4 Value4;
  static T4 ElementTypeI(vtkm::internal::IndexTag<4>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>)
  {
    return this->Value4;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>) const
  {
    return this->Value4;
  }

  T5 Value5;
  static T5 ElementTypeI(vtkm::internal::IndexTag<5>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>)
  {
    return this->Value5;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>) const
  {
    return this->Value5;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 6;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2, T3, T4, T5>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
    , Value3(std::forward<A3>(a3))
    , Value4(std::forward<A4>(a4))
    , Value5(std::forward<A5>(a5))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
class Tuple<T0, T1, T2, T3, T4, T5, T6>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }

  T3 Value3;
  static T3 ElementTypeI(vtkm::internal::IndexTag<3>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>)
  {
    return this->Value3;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>) const
  {
    return this->Value3;
  }

  T4 Value4;
  static T4 ElementTypeI(vtkm::internal::IndexTag<4>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>)
  {
    return this->Value4;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>) const
  {
    return this->Value4;
  }

  T5 Value5;
  static T5 ElementTypeI(vtkm::internal::IndexTag<5>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>)
  {
    return this->Value5;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>) const
  {
    return this->Value5;
  }

  T6 Value6;
  static T6 ElementTypeI(vtkm::internal::IndexTag<6>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>)
  {
    return this->Value6;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>) const
  {
    return this->Value6;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 7;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2, T3, T4, T5, T6>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
    , Value3(std::forward<A3>(a3))
    , Value4(std::forward<A4>(a4))
    , Value5(std::forward<A5>(a5))
    , Value6(std::forward<A6>(a6))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
class Tuple<T0, T1, T2, T3, T4, T5, T6, T7>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }

  T3 Value3;
  static T3 ElementTypeI(vtkm::internal::IndexTag<3>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>)
  {
    return this->Value3;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>) const
  {
    return this->Value3;
  }

  T4 Value4;
  static T4 ElementTypeI(vtkm::internal::IndexTag<4>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>)
  {
    return this->Value4;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>) const
  {
    return this->Value4;
  }

  T5 Value5;
  static T5 ElementTypeI(vtkm::internal::IndexTag<5>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>)
  {
    return this->Value5;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>) const
  {
    return this->Value5;
  }

  T6 Value6;
  static T6 ElementTypeI(vtkm::internal::IndexTag<6>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>)
  {
    return this->Value6;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>) const
  {
    return this->Value6;
  }

  T7 Value7;
  static T7 ElementTypeI(vtkm::internal::IndexTag<7>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>)
  {
    return this->Value7;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>) const
  {
    return this->Value7;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 8;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2, T3, T4, T5, T6, T7>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
    , Value3(std::forward<A3>(a3))
    , Value4(std::forward<A4>(a4))
    , Value5(std::forward<A5>(a5))
    , Value6(std::forward<A6>(a6))
    , Value7(std::forward<A7>(a7))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
class Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }

  T3 Value3;
  static T3 ElementTypeI(vtkm::internal::IndexTag<3>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>)
  {
    return this->Value3;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>) const
  {
    return this->Value3;
  }

  T4 Value4;
  static T4 ElementTypeI(vtkm::internal::IndexTag<4>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>)
  {
    return this->Value4;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>) const
  {
    return this->Value4;
  }

  T5 Value5;
  static T5 ElementTypeI(vtkm::internal::IndexTag<5>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>)
  {
    return this->Value5;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>) const
  {
    return this->Value5;
  }

  T6 Value6;
  static T6 ElementTypeI(vtkm::internal::IndexTag<6>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>)
  {
    return this->Value6;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>) const
  {
    return this->Value6;
  }

  T7 Value7;
  static T7 ElementTypeI(vtkm::internal::IndexTag<7>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>)
  {
    return this->Value7;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>) const
  {
    return this->Value7;
  }

  T8 Value8;
  static T8 ElementTypeI(vtkm::internal::IndexTag<8>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>)
  {
    return this->Value8;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>) const
  {
    return this->Value8;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 9;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
    , Value3(std::forward<A3>(a3))
    , Value4(std::forward<A4>(a4))
    , Value5(std::forward<A5>(a5))
    , Value6(std::forward<A6>(a6))
    , Value7(std::forward<A7>(a7))
    , Value8(std::forward<A8>(a8))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
class Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }

  T3 Value3;
  static T3 ElementTypeI(vtkm::internal::IndexTag<3>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>)
  {
    return this->Value3;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>) const
  {
    return this->Value3;
  }

  T4 Value4;
  static T4 ElementTypeI(vtkm::internal::IndexTag<4>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>)
  {
    return this->Value4;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>) const
  {
    return this->Value4;
  }

  T5 Value5;
  static T5 ElementTypeI(vtkm::internal::IndexTag<5>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>)
  {
    return this->Value5;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>) const
  {
    return this->Value5;
  }

  T6 Value6;
  static T6 ElementTypeI(vtkm::internal::IndexTag<6>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>)
  {
    return this->Value6;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>) const
  {
    return this->Value6;
  }

  T7 Value7;
  static T7 ElementTypeI(vtkm::internal::IndexTag<7>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>)
  {
    return this->Value7;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>) const
  {
    return this->Value7;
  }

  T8 Value8;
  static T8 ElementTypeI(vtkm::internal::IndexTag<8>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>)
  {
    return this->Value8;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>) const
  {
    return this->Value8;
  }

  T9 Value9;
  static T9 ElementTypeI(vtkm::internal::IndexTag<9>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>)
  {
    return this->Value9;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>) const
  {
    return this->Value9;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 10;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
    , Value3(std::forward<A3>(a3))
    , Value4(std::forward<A4>(a4))
    , Value5(std::forward<A5>(a5))
    , Value6(std::forward<A6>(a6))
    , Value7(std::forward<A7>(a7))
    , Value8(std::forward<A8>(a8))
    , Value9(std::forward<A9>(a9))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10>
class Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }

  T3 Value3;
  static T3 ElementTypeI(vtkm::internal::IndexTag<3>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>)
  {
    return this->Value3;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>) const
  {
    return this->Value3;
  }

  T4 Value4;
  static T4 ElementTypeI(vtkm::internal::IndexTag<4>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>)
  {
    return this->Value4;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>) const
  {
    return this->Value4;
  }

  T5 Value5;
  static T5 ElementTypeI(vtkm::internal::IndexTag<5>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>)
  {
    return this->Value5;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>) const
  {
    return this->Value5;
  }

  T6 Value6;
  static T6 ElementTypeI(vtkm::internal::IndexTag<6>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>)
  {
    return this->Value6;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>) const
  {
    return this->Value6;
  }

  T7 Value7;
  static T7 ElementTypeI(vtkm::internal::IndexTag<7>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>)
  {
    return this->Value7;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>) const
  {
    return this->Value7;
  }

  T8 Value8;
  static T8 ElementTypeI(vtkm::internal::IndexTag<8>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>)
  {
    return this->Value8;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>) const
  {
    return this->Value8;
  }

  T9 Value9;
  static T9 ElementTypeI(vtkm::internal::IndexTag<9>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>)
  {
    return this->Value9;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>) const
  {
    return this->Value9;
  }

  T10 Value10;
  static T10 ElementTypeI(vtkm::internal::IndexTag<10>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>)
  {
    return this->Value10;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>) const
  {
    return this->Value10;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 11;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9, A10&& a10)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
    , Value3(std::forward<A3>(a3))
    , Value4(std::forward<A4>(a4))
    , Value5(std::forward<A5>(a5))
    , Value6(std::forward<A6>(a6))
    , Value7(std::forward<A7>(a7))
    , Value8(std::forward<A8>(a8))
    , Value9(std::forward<A9>(a9))
    , Value10(std::forward<A10>(a10))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11>
class Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }

  T3 Value3;
  static T3 ElementTypeI(vtkm::internal::IndexTag<3>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>)
  {
    return this->Value3;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>) const
  {
    return this->Value3;
  }

  T4 Value4;
  static T4 ElementTypeI(vtkm::internal::IndexTag<4>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>)
  {
    return this->Value4;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>) const
  {
    return this->Value4;
  }

  T5 Value5;
  static T5 ElementTypeI(vtkm::internal::IndexTag<5>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>)
  {
    return this->Value5;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>) const
  {
    return this->Value5;
  }

  T6 Value6;
  static T6 ElementTypeI(vtkm::internal::IndexTag<6>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>)
  {
    return this->Value6;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>) const
  {
    return this->Value6;
  }

  T7 Value7;
  static T7 ElementTypeI(vtkm::internal::IndexTag<7>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>)
  {
    return this->Value7;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>) const
  {
    return this->Value7;
  }

  T8 Value8;
  static T8 ElementTypeI(vtkm::internal::IndexTag<8>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>)
  {
    return this->Value8;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>) const
  {
    return this->Value8;
  }

  T9 Value9;
  static T9 ElementTypeI(vtkm::internal::IndexTag<9>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>)
  {
    return this->Value9;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>) const
  {
    return this->Value9;
  }

  T10 Value10;
  static T10 ElementTypeI(vtkm::internal::IndexTag<10>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>)
  {
    return this->Value10;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>) const
  {
    return this->Value10;
  }

  T11 Value11;
  static T11 ElementTypeI(vtkm::internal::IndexTag<11>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>)
  {
    return this->Value11;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>) const
  {
    return this->Value11;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 12;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9, A10&& a10, A11&& a11)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
    , Value3(std::forward<A3>(a3))
    , Value4(std::forward<A4>(a4))
    , Value5(std::forward<A5>(a5))
    , Value6(std::forward<A6>(a6))
    , Value7(std::forward<A7>(a7))
    , Value8(std::forward<A8>(a8))
    , Value9(std::forward<A9>(a9))
    , Value10(std::forward<A10>(a10))
    , Value11(std::forward<A11>(a11))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12>
class Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }

  T3 Value3;
  static T3 ElementTypeI(vtkm::internal::IndexTag<3>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>)
  {
    return this->Value3;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>) const
  {
    return this->Value3;
  }

  T4 Value4;
  static T4 ElementTypeI(vtkm::internal::IndexTag<4>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>)
  {
    return this->Value4;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>) const
  {
    return this->Value4;
  }

  T5 Value5;
  static T5 ElementTypeI(vtkm::internal::IndexTag<5>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>)
  {
    return this->Value5;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>) const
  {
    return this->Value5;
  }

  T6 Value6;
  static T6 ElementTypeI(vtkm::internal::IndexTag<6>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>)
  {
    return this->Value6;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>) const
  {
    return this->Value6;
  }

  T7 Value7;
  static T7 ElementTypeI(vtkm::internal::IndexTag<7>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>)
  {
    return this->Value7;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>) const
  {
    return this->Value7;
  }

  T8 Value8;
  static T8 ElementTypeI(vtkm::internal::IndexTag<8>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>)
  {
    return this->Value8;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>) const
  {
    return this->Value8;
  }

  T9 Value9;
  static T9 ElementTypeI(vtkm::internal::IndexTag<9>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>)
  {
    return this->Value9;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>) const
  {
    return this->Value9;
  }

  T10 Value10;
  static T10 ElementTypeI(vtkm::internal::IndexTag<10>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>)
  {
    return this->Value10;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>) const
  {
    return this->Value10;
  }

  T11 Value11;
  static T11 ElementTypeI(vtkm::internal::IndexTag<11>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>)
  {
    return this->Value11;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>) const
  {
    return this->Value11;
  }

  T12 Value12;
  static T12 ElementTypeI(vtkm::internal::IndexTag<12>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T12>& GetImpl(vtkm::internal::IndexTag<12>)
  {
    return this->Value12;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T12>& GetImpl(vtkm::internal::IndexTag<12>) const
  {
    return this->Value12;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 13;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9, A10&& a10, A11&& a11, A12&& a12)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
    , Value3(std::forward<A3>(a3))
    , Value4(std::forward<A4>(a4))
    , Value5(std::forward<A5>(a5))
    , Value6(std::forward<A6>(a6))
    , Value7(std::forward<A7>(a7))
    , Value8(std::forward<A8>(a8))
    , Value9(std::forward<A9>(a9))
    , Value10(std::forward<A10>(a10))
    , Value11(std::forward<A11>(a11))
    , Value12(std::forward<A12>(a12))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13>
class Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }

  T3 Value3;
  static T3 ElementTypeI(vtkm::internal::IndexTag<3>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>)
  {
    return this->Value3;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>) const
  {
    return this->Value3;
  }

  T4 Value4;
  static T4 ElementTypeI(vtkm::internal::IndexTag<4>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>)
  {
    return this->Value4;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>) const
  {
    return this->Value4;
  }

  T5 Value5;
  static T5 ElementTypeI(vtkm::internal::IndexTag<5>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>)
  {
    return this->Value5;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>) const
  {
    return this->Value5;
  }

  T6 Value6;
  static T6 ElementTypeI(vtkm::internal::IndexTag<6>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>)
  {
    return this->Value6;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>) const
  {
    return this->Value6;
  }

  T7 Value7;
  static T7 ElementTypeI(vtkm::internal::IndexTag<7>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>)
  {
    return this->Value7;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>) const
  {
    return this->Value7;
  }

  T8 Value8;
  static T8 ElementTypeI(vtkm::internal::IndexTag<8>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>)
  {
    return this->Value8;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>) const
  {
    return this->Value8;
  }

  T9 Value9;
  static T9 ElementTypeI(vtkm::internal::IndexTag<9>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>)
  {
    return this->Value9;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>) const
  {
    return this->Value9;
  }

  T10 Value10;
  static T10 ElementTypeI(vtkm::internal::IndexTag<10>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>)
  {
    return this->Value10;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>) const
  {
    return this->Value10;
  }

  T11 Value11;
  static T11 ElementTypeI(vtkm::internal::IndexTag<11>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>)
  {
    return this->Value11;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>) const
  {
    return this->Value11;
  }

  T12 Value12;
  static T12 ElementTypeI(vtkm::internal::IndexTag<12>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T12>& GetImpl(vtkm::internal::IndexTag<12>)
  {
    return this->Value12;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T12>& GetImpl(vtkm::internal::IndexTag<12>) const
  {
    return this->Value12;
  }

  T13 Value13;
  static T13 ElementTypeI(vtkm::internal::IndexTag<13>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T13>& GetImpl(vtkm::internal::IndexTag<13>)
  {
    return this->Value13;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T13>& GetImpl(vtkm::internal::IndexTag<13>) const
  {
    return this->Value13;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 14;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9, A10&& a10, A11&& a11, A12&& a12, A13&& a13)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
    , Value3(std::forward<A3>(a3))
    , Value4(std::forward<A4>(a4))
    , Value5(std::forward<A5>(a5))
    , Value6(std::forward<A6>(a6))
    , Value7(std::forward<A7>(a7))
    , Value8(std::forward<A8>(a8))
    , Value9(std::forward<A9>(a9))
    , Value10(std::forward<A10>(a10))
    , Value11(std::forward<A11>(a11))
    , Value12(std::forward<A12>(a12))
    , Value13(std::forward<A13>(a13))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14>
class Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }

  T3 Value3;
  static T3 ElementTypeI(vtkm::internal::IndexTag<3>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>)
  {
    return this->Value3;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>) const
  {
    return this->Value3;
  }

  T4 Value4;
  static T4 ElementTypeI(vtkm::internal::IndexTag<4>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>)
  {
    return this->Value4;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>) const
  {
    return this->Value4;
  }

  T5 Value5;
  static T5 ElementTypeI(vtkm::internal::IndexTag<5>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>)
  {
    return this->Value5;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>) const
  {
    return this->Value5;
  }

  T6 Value6;
  static T6 ElementTypeI(vtkm::internal::IndexTag<6>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>)
  {
    return this->Value6;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>) const
  {
    return this->Value6;
  }

  T7 Value7;
  static T7 ElementTypeI(vtkm::internal::IndexTag<7>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>)
  {
    return this->Value7;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>) const
  {
    return this->Value7;
  }

  T8 Value8;
  static T8 ElementTypeI(vtkm::internal::IndexTag<8>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>)
  {
    return this->Value8;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>) const
  {
    return this->Value8;
  }

  T9 Value9;
  static T9 ElementTypeI(vtkm::internal::IndexTag<9>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>)
  {
    return this->Value9;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>) const
  {
    return this->Value9;
  }

  T10 Value10;
  static T10 ElementTypeI(vtkm::internal::IndexTag<10>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>)
  {
    return this->Value10;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>) const
  {
    return this->Value10;
  }

  T11 Value11;
  static T11 ElementTypeI(vtkm::internal::IndexTag<11>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>)
  {
    return this->Value11;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>) const
  {
    return this->Value11;
  }

  T12 Value12;
  static T12 ElementTypeI(vtkm::internal::IndexTag<12>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T12>& GetImpl(vtkm::internal::IndexTag<12>)
  {
    return this->Value12;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T12>& GetImpl(vtkm::internal::IndexTag<12>) const
  {
    return this->Value12;
  }

  T13 Value13;
  static T13 ElementTypeI(vtkm::internal::IndexTag<13>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T13>& GetImpl(vtkm::internal::IndexTag<13>)
  {
    return this->Value13;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T13>& GetImpl(vtkm::internal::IndexTag<13>) const
  {
    return this->Value13;
  }

  T14 Value14;
  static T14 ElementTypeI(vtkm::internal::IndexTag<14>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T14>& GetImpl(vtkm::internal::IndexTag<14>)
  {
    return this->Value14;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T14>& GetImpl(vtkm::internal::IndexTag<14>) const
  {
    return this->Value14;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 15;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9, A10&& a10, A11&& a11, A12&& a12, A13&& a13, A14&& a14)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
    , Value3(std::forward<A3>(a3))
    , Value4(std::forward<A4>(a4))
    , Value5(std::forward<A5>(a5))
    , Value6(std::forward<A6>(a6))
    , Value7(std::forward<A7>(a7))
    , Value8(std::forward<A8>(a8))
    , Value9(std::forward<A9>(a9))
    , Value10(std::forward<A10>(a10))
    , Value11(std::forward<A11>(a11))
    , Value12(std::forward<A12>(a12))
    , Value13(std::forward<A13>(a13))
    , Value14(std::forward<A14>(a14))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15>
class Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }

  T3 Value3;
  static T3 ElementTypeI(vtkm::internal::IndexTag<3>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>)
  {
    return this->Value3;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>) const
  {
    return this->Value3;
  }

  T4 Value4;
  static T4 ElementTypeI(vtkm::internal::IndexTag<4>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>)
  {
    return this->Value4;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>) const
  {
    return this->Value4;
  }

  T5 Value5;
  static T5 ElementTypeI(vtkm::internal::IndexTag<5>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>)
  {
    return this->Value5;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>) const
  {
    return this->Value5;
  }

  T6 Value6;
  static T6 ElementTypeI(vtkm::internal::IndexTag<6>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>)
  {
    return this->Value6;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>) const
  {
    return this->Value6;
  }

  T7 Value7;
  static T7 ElementTypeI(vtkm::internal::IndexTag<7>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>)
  {
    return this->Value7;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>) const
  {
    return this->Value7;
  }

  T8 Value8;
  static T8 ElementTypeI(vtkm::internal::IndexTag<8>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>)
  {
    return this->Value8;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>) const
  {
    return this->Value8;
  }

  T9 Value9;
  static T9 ElementTypeI(vtkm::internal::IndexTag<9>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>)
  {
    return this->Value9;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>) const
  {
    return this->Value9;
  }

  T10 Value10;
  static T10 ElementTypeI(vtkm::internal::IndexTag<10>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>)
  {
    return this->Value10;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>) const
  {
    return this->Value10;
  }

  T11 Value11;
  static T11 ElementTypeI(vtkm::internal::IndexTag<11>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>)
  {
    return this->Value11;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>) const
  {
    return this->Value11;
  }

  T12 Value12;
  static T12 ElementTypeI(vtkm::internal::IndexTag<12>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T12>& GetImpl(vtkm::internal::IndexTag<12>)
  {
    return this->Value12;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T12>& GetImpl(vtkm::internal::IndexTag<12>) const
  {
    return this->Value12;
  }

  T13 Value13;
  static T13 ElementTypeI(vtkm::internal::IndexTag<13>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T13>& GetImpl(vtkm::internal::IndexTag<13>)
  {
    return this->Value13;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T13>& GetImpl(vtkm::internal::IndexTag<13>) const
  {
    return this->Value13;
  }

  T14 Value14;
  static T14 ElementTypeI(vtkm::internal::IndexTag<14>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T14>& GetImpl(vtkm::internal::IndexTag<14>)
  {
    return this->Value14;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T14>& GetImpl(vtkm::internal::IndexTag<14>) const
  {
    return this->Value14;
  }

  T15 Value15;
  static T15 ElementTypeI(vtkm::internal::IndexTag<15>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T15>& GetImpl(vtkm::internal::IndexTag<15>)
  {
    return this->Value15;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T15>& GetImpl(vtkm::internal::IndexTag<15>) const
  {
    return this->Value15;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 16;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14, typename A15>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9, A10&& a10, A11&& a11, A12&& a12, A13&& a13, A14&& a14, A15&& a15)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
    , Value3(std::forward<A3>(a3))
    , Value4(std::forward<A4>(a4))
    , Value5(std::forward<A5>(a5))
    , Value6(std::forward<A6>(a6))
    , Value7(std::forward<A7>(a7))
    , Value8(std::forward<A8>(a8))
    , Value9(std::forward<A9>(a9))
    , Value10(std::forward<A10>(a10))
    , Value11(std::forward<A11>(a11))
    , Value12(std::forward<A12>(a12))
    , Value13(std::forward<A13>(a13))
    , Value14(std::forward<A14>(a14))
    , Value15(std::forward<A15>(a15))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15, typename T16>
class Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }

  T3 Value3;
  static T3 ElementTypeI(vtkm::internal::IndexTag<3>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>)
  {
    return this->Value3;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>) const
  {
    return this->Value3;
  }

  T4 Value4;
  static T4 ElementTypeI(vtkm::internal::IndexTag<4>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>)
  {
    return this->Value4;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>) const
  {
    return this->Value4;
  }

  T5 Value5;
  static T5 ElementTypeI(vtkm::internal::IndexTag<5>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>)
  {
    return this->Value5;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>) const
  {
    return this->Value5;
  }

  T6 Value6;
  static T6 ElementTypeI(vtkm::internal::IndexTag<6>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>)
  {
    return this->Value6;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>) const
  {
    return this->Value6;
  }

  T7 Value7;
  static T7 ElementTypeI(vtkm::internal::IndexTag<7>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>)
  {
    return this->Value7;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>) const
  {
    return this->Value7;
  }

  T8 Value8;
  static T8 ElementTypeI(vtkm::internal::IndexTag<8>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>)
  {
    return this->Value8;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>) const
  {
    return this->Value8;
  }

  T9 Value9;
  static T9 ElementTypeI(vtkm::internal::IndexTag<9>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>)
  {
    return this->Value9;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>) const
  {
    return this->Value9;
  }

  T10 Value10;
  static T10 ElementTypeI(vtkm::internal::IndexTag<10>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>)
  {
    return this->Value10;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>) const
  {
    return this->Value10;
  }

  T11 Value11;
  static T11 ElementTypeI(vtkm::internal::IndexTag<11>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>)
  {
    return this->Value11;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>) const
  {
    return this->Value11;
  }

  T12 Value12;
  static T12 ElementTypeI(vtkm::internal::IndexTag<12>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T12>& GetImpl(vtkm::internal::IndexTag<12>)
  {
    return this->Value12;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T12>& GetImpl(vtkm::internal::IndexTag<12>) const
  {
    return this->Value12;
  }

  T13 Value13;
  static T13 ElementTypeI(vtkm::internal::IndexTag<13>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T13>& GetImpl(vtkm::internal::IndexTag<13>)
  {
    return this->Value13;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T13>& GetImpl(vtkm::internal::IndexTag<13>) const
  {
    return this->Value13;
  }

  T14 Value14;
  static T14 ElementTypeI(vtkm::internal::IndexTag<14>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T14>& GetImpl(vtkm::internal::IndexTag<14>)
  {
    return this->Value14;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T14>& GetImpl(vtkm::internal::IndexTag<14>) const
  {
    return this->Value14;
  }

  T15 Value15;
  static T15 ElementTypeI(vtkm::internal::IndexTag<15>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T15>& GetImpl(vtkm::internal::IndexTag<15>)
  {
    return this->Value15;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T15>& GetImpl(vtkm::internal::IndexTag<15>) const
  {
    return this->Value15;
  }

  T16 Value16;
  static T16 ElementTypeI(vtkm::internal::IndexTag<16>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T16>& GetImpl(vtkm::internal::IndexTag<16>)
  {
    return this->Value16;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T16>& GetImpl(vtkm::internal::IndexTag<16>) const
  {
    return this->Value16;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 17;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14, typename A15, typename A16>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9, A10&& a10, A11&& a11, A12&& a12, A13&& a13, A14&& a14, A15&& a15, A16&& a16)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
    , Value3(std::forward<A3>(a3))
    , Value4(std::forward<A4>(a4))
    , Value5(std::forward<A5>(a5))
    , Value6(std::forward<A6>(a6))
    , Value7(std::forward<A7>(a7))
    , Value8(std::forward<A8>(a8))
    , Value9(std::forward<A9>(a9))
    , Value10(std::forward<A10>(a10))
    , Value11(std::forward<A11>(a11))
    , Value12(std::forward<A12>(a12))
    , Value13(std::forward<A13>(a13))
    , Value14(std::forward<A14>(a14))
    , Value15(std::forward<A15>(a15))
    , Value16(std::forward<A16>(a16))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15, Value16))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15, Value16);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15, Value16))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15, Value16);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15, typename T16, typename T17>
class Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }

  T3 Value3;
  static T3 ElementTypeI(vtkm::internal::IndexTag<3>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>)
  {
    return this->Value3;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>) const
  {
    return this->Value3;
  }

  T4 Value4;
  static T4 ElementTypeI(vtkm::internal::IndexTag<4>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>)
  {
    return this->Value4;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>) const
  {
    return this->Value4;
  }

  T5 Value5;
  static T5 ElementTypeI(vtkm::internal::IndexTag<5>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>)
  {
    return this->Value5;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>) const
  {
    return this->Value5;
  }

  T6 Value6;
  static T6 ElementTypeI(vtkm::internal::IndexTag<6>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>)
  {
    return this->Value6;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>) const
  {
    return this->Value6;
  }

  T7 Value7;
  static T7 ElementTypeI(vtkm::internal::IndexTag<7>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>)
  {
    return this->Value7;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>) const
  {
    return this->Value7;
  }

  T8 Value8;
  static T8 ElementTypeI(vtkm::internal::IndexTag<8>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>)
  {
    return this->Value8;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>) const
  {
    return this->Value8;
  }

  T9 Value9;
  static T9 ElementTypeI(vtkm::internal::IndexTag<9>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>)
  {
    return this->Value9;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>) const
  {
    return this->Value9;
  }

  T10 Value10;
  static T10 ElementTypeI(vtkm::internal::IndexTag<10>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>)
  {
    return this->Value10;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>) const
  {
    return this->Value10;
  }

  T11 Value11;
  static T11 ElementTypeI(vtkm::internal::IndexTag<11>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>)
  {
    return this->Value11;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>) const
  {
    return this->Value11;
  }

  T12 Value12;
  static T12 ElementTypeI(vtkm::internal::IndexTag<12>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T12>& GetImpl(vtkm::internal::IndexTag<12>)
  {
    return this->Value12;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T12>& GetImpl(vtkm::internal::IndexTag<12>) const
  {
    return this->Value12;
  }

  T13 Value13;
  static T13 ElementTypeI(vtkm::internal::IndexTag<13>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T13>& GetImpl(vtkm::internal::IndexTag<13>)
  {
    return this->Value13;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T13>& GetImpl(vtkm::internal::IndexTag<13>) const
  {
    return this->Value13;
  }

  T14 Value14;
  static T14 ElementTypeI(vtkm::internal::IndexTag<14>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T14>& GetImpl(vtkm::internal::IndexTag<14>)
  {
    return this->Value14;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T14>& GetImpl(vtkm::internal::IndexTag<14>) const
  {
    return this->Value14;
  }

  T15 Value15;
  static T15 ElementTypeI(vtkm::internal::IndexTag<15>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T15>& GetImpl(vtkm::internal::IndexTag<15>)
  {
    return this->Value15;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T15>& GetImpl(vtkm::internal::IndexTag<15>) const
  {
    return this->Value15;
  }

  T16 Value16;
  static T16 ElementTypeI(vtkm::internal::IndexTag<16>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T16>& GetImpl(vtkm::internal::IndexTag<16>)
  {
    return this->Value16;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T16>& GetImpl(vtkm::internal::IndexTag<16>) const
  {
    return this->Value16;
  }

  T17 Value17;
  static T17 ElementTypeI(vtkm::internal::IndexTag<17>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T17>& GetImpl(vtkm::internal::IndexTag<17>)
  {
    return this->Value17;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T17>& GetImpl(vtkm::internal::IndexTag<17>) const
  {
    return this->Value17;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 18;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14, typename A15, typename A16, typename A17>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9, A10&& a10, A11&& a11, A12&& a12, A13&& a13, A14&& a14, A15&& a15, A16&& a16, A17&& a17)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
    , Value3(std::forward<A3>(a3))
    , Value4(std::forward<A4>(a4))
    , Value5(std::forward<A5>(a5))
    , Value6(std::forward<A6>(a6))
    , Value7(std::forward<A7>(a7))
    , Value8(std::forward<A8>(a8))
    , Value9(std::forward<A9>(a9))
    , Value10(std::forward<A10>(a10))
    , Value11(std::forward<A11>(a11))
    , Value12(std::forward<A12>(a12))
    , Value13(std::forward<A13>(a13))
    , Value14(std::forward<A14>(a14))
    , Value15(std::forward<A15>(a15))
    , Value16(std::forward<A16>(a16))
    , Value17(std::forward<A17>(a17))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15, Value16, Value17))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15, Value16, Value17);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15, Value16, Value17))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15, Value16, Value17);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15, typename T16, typename T17, typename T18>
class Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }

  T3 Value3;
  static T3 ElementTypeI(vtkm::internal::IndexTag<3>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>)
  {
    return this->Value3;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>) const
  {
    return this->Value3;
  }

  T4 Value4;
  static T4 ElementTypeI(vtkm::internal::IndexTag<4>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>)
  {
    return this->Value4;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>) const
  {
    return this->Value4;
  }

  T5 Value5;
  static T5 ElementTypeI(vtkm::internal::IndexTag<5>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>)
  {
    return this->Value5;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>) const
  {
    return this->Value5;
  }

  T6 Value6;
  static T6 ElementTypeI(vtkm::internal::IndexTag<6>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>)
  {
    return this->Value6;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>) const
  {
    return this->Value6;
  }

  T7 Value7;
  static T7 ElementTypeI(vtkm::internal::IndexTag<7>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>)
  {
    return this->Value7;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>) const
  {
    return this->Value7;
  }

  T8 Value8;
  static T8 ElementTypeI(vtkm::internal::IndexTag<8>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>)
  {
    return this->Value8;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>) const
  {
    return this->Value8;
  }

  T9 Value9;
  static T9 ElementTypeI(vtkm::internal::IndexTag<9>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>)
  {
    return this->Value9;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>) const
  {
    return this->Value9;
  }

  T10 Value10;
  static T10 ElementTypeI(vtkm::internal::IndexTag<10>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>)
  {
    return this->Value10;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>) const
  {
    return this->Value10;
  }

  T11 Value11;
  static T11 ElementTypeI(vtkm::internal::IndexTag<11>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>)
  {
    return this->Value11;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>) const
  {
    return this->Value11;
  }

  T12 Value12;
  static T12 ElementTypeI(vtkm::internal::IndexTag<12>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T12>& GetImpl(vtkm::internal::IndexTag<12>)
  {
    return this->Value12;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T12>& GetImpl(vtkm::internal::IndexTag<12>) const
  {
    return this->Value12;
  }

  T13 Value13;
  static T13 ElementTypeI(vtkm::internal::IndexTag<13>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T13>& GetImpl(vtkm::internal::IndexTag<13>)
  {
    return this->Value13;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T13>& GetImpl(vtkm::internal::IndexTag<13>) const
  {
    return this->Value13;
  }

  T14 Value14;
  static T14 ElementTypeI(vtkm::internal::IndexTag<14>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T14>& GetImpl(vtkm::internal::IndexTag<14>)
  {
    return this->Value14;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T14>& GetImpl(vtkm::internal::IndexTag<14>) const
  {
    return this->Value14;
  }

  T15 Value15;
  static T15 ElementTypeI(vtkm::internal::IndexTag<15>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T15>& GetImpl(vtkm::internal::IndexTag<15>)
  {
    return this->Value15;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T15>& GetImpl(vtkm::internal::IndexTag<15>) const
  {
    return this->Value15;
  }

  T16 Value16;
  static T16 ElementTypeI(vtkm::internal::IndexTag<16>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T16>& GetImpl(vtkm::internal::IndexTag<16>)
  {
    return this->Value16;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T16>& GetImpl(vtkm::internal::IndexTag<16>) const
  {
    return this->Value16;
  }

  T17 Value17;
  static T17 ElementTypeI(vtkm::internal::IndexTag<17>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T17>& GetImpl(vtkm::internal::IndexTag<17>)
  {
    return this->Value17;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T17>& GetImpl(vtkm::internal::IndexTag<17>) const
  {
    return this->Value17;
  }

  T18 Value18;
  static T18 ElementTypeI(vtkm::internal::IndexTag<18>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T18>& GetImpl(vtkm::internal::IndexTag<18>)
  {
    return this->Value18;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T18>& GetImpl(vtkm::internal::IndexTag<18>) const
  {
    return this->Value18;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 19;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14, typename A15, typename A16, typename A17, typename A18>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9, A10&& a10, A11&& a11, A12&& a12, A13&& a13, A14&& a14, A15&& a15, A16&& a16, A17&& a17, A18&& a18)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
    , Value3(std::forward<A3>(a3))
    , Value4(std::forward<A4>(a4))
    , Value5(std::forward<A5>(a5))
    , Value6(std::forward<A6>(a6))
    , Value7(std::forward<A7>(a7))
    , Value8(std::forward<A8>(a8))
    , Value9(std::forward<A9>(a9))
    , Value10(std::forward<A10>(a10))
    , Value11(std::forward<A11>(a11))
    , Value12(std::forward<A12>(a12))
    , Value13(std::forward<A13>(a13))
    , Value14(std::forward<A14>(a14))
    , Value15(std::forward<A15>(a15))
    , Value16(std::forward<A16>(a16))
    , Value17(std::forward<A17>(a17))
    , Value18(std::forward<A18>(a18))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15, Value16, Value17, Value18))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15, Value16, Value17, Value18);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15, Value16, Value17, Value18))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15, Value16, Value17, Value18);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15, typename T16, typename T17, typename T18, typename T19>
class Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }

  T3 Value3;
  static T3 ElementTypeI(vtkm::internal::IndexTag<3>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>)
  {
    return this->Value3;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>) const
  {
    return this->Value3;
  }

  T4 Value4;
  static T4 ElementTypeI(vtkm::internal::IndexTag<4>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>)
  {
    return this->Value4;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>) const
  {
    return this->Value4;
  }

  T5 Value5;
  static T5 ElementTypeI(vtkm::internal::IndexTag<5>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>)
  {
    return this->Value5;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>) const
  {
    return this->Value5;
  }

  T6 Value6;
  static T6 ElementTypeI(vtkm::internal::IndexTag<6>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>)
  {
    return this->Value6;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>) const
  {
    return this->Value6;
  }

  T7 Value7;
  static T7 ElementTypeI(vtkm::internal::IndexTag<7>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>)
  {
    return this->Value7;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>) const
  {
    return this->Value7;
  }

  T8 Value8;
  static T8 ElementTypeI(vtkm::internal::IndexTag<8>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>)
  {
    return this->Value8;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>) const
  {
    return this->Value8;
  }

  T9 Value9;
  static T9 ElementTypeI(vtkm::internal::IndexTag<9>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>)
  {
    return this->Value9;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>) const
  {
    return this->Value9;
  }

  T10 Value10;
  static T10 ElementTypeI(vtkm::internal::IndexTag<10>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>)
  {
    return this->Value10;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>) const
  {
    return this->Value10;
  }

  T11 Value11;
  static T11 ElementTypeI(vtkm::internal::IndexTag<11>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>)
  {
    return this->Value11;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>) const
  {
    return this->Value11;
  }

  T12 Value12;
  static T12 ElementTypeI(vtkm::internal::IndexTag<12>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T12>& GetImpl(vtkm::internal::IndexTag<12>)
  {
    return this->Value12;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T12>& GetImpl(vtkm::internal::IndexTag<12>) const
  {
    return this->Value12;
  }

  T13 Value13;
  static T13 ElementTypeI(vtkm::internal::IndexTag<13>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T13>& GetImpl(vtkm::internal::IndexTag<13>)
  {
    return this->Value13;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T13>& GetImpl(vtkm::internal::IndexTag<13>) const
  {
    return this->Value13;
  }

  T14 Value14;
  static T14 ElementTypeI(vtkm::internal::IndexTag<14>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T14>& GetImpl(vtkm::internal::IndexTag<14>)
  {
    return this->Value14;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T14>& GetImpl(vtkm::internal::IndexTag<14>) const
  {
    return this->Value14;
  }

  T15 Value15;
  static T15 ElementTypeI(vtkm::internal::IndexTag<15>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T15>& GetImpl(vtkm::internal::IndexTag<15>)
  {
    return this->Value15;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T15>& GetImpl(vtkm::internal::IndexTag<15>) const
  {
    return this->Value15;
  }

  T16 Value16;
  static T16 ElementTypeI(vtkm::internal::IndexTag<16>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T16>& GetImpl(vtkm::internal::IndexTag<16>)
  {
    return this->Value16;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T16>& GetImpl(vtkm::internal::IndexTag<16>) const
  {
    return this->Value16;
  }

  T17 Value17;
  static T17 ElementTypeI(vtkm::internal::IndexTag<17>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T17>& GetImpl(vtkm::internal::IndexTag<17>)
  {
    return this->Value17;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T17>& GetImpl(vtkm::internal::IndexTag<17>) const
  {
    return this->Value17;
  }

  T18 Value18;
  static T18 ElementTypeI(vtkm::internal::IndexTag<18>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T18>& GetImpl(vtkm::internal::IndexTag<18>)
  {
    return this->Value18;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T18>& GetImpl(vtkm::internal::IndexTag<18>) const
  {
    return this->Value18;
  }

  T19 Value19;
  static T19 ElementTypeI(vtkm::internal::IndexTag<19>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T19>& GetImpl(vtkm::internal::IndexTag<19>)
  {
    return this->Value19;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T19>& GetImpl(vtkm::internal::IndexTag<19>) const
  {
    return this->Value19;
  }


  // Invalid indices
  template <vtkm::IdComponent Index>
  static vtkm::internal::NullType ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size = 20;
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14, typename A15, typename A16, typename A17, typename A18, typename A19>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9, A10&& a10, A11&& a11, A12&& a12, A13&& a13, A14&& a14, A15&& a15, A16&& a16, A17&& a17, A18&& a18, A19&& a19)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
    , Value3(std::forward<A3>(a3))
    , Value4(std::forward<A4>(a4))
    , Value5(std::forward<A5>(a5))
    , Value6(std::forward<A6>(a6))
    , Value7(std::forward<A7>(a7))
    , Value8(std::forward<A8>(a8))
    , Value9(std::forward<A9>(a9))
    , Value10(std::forward<A10>(a10))
    , Value11(std::forward<A11>(a11))
    , Value12(std::forward<A12>(a12))
    , Value13(std::forward<A13>(a13))
    , Value14(std::forward<A14>(a14))
    , Value15(std::forward<A15>(a15))
    , Value16(std::forward<A16>(a16))
    , Value17(std::forward<A17>(a17))
    , Value18(std::forward<A18>(a18))
    , Value19(std::forward<A19>(a19))
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15, Value16, Value17, Value18, Value19))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15, Value16, Value17, Value18, Value19);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15, Value16, Value17, Value18, Value19))
  {
    return f(std::forward<Args>(args)..., Value0, Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8, Value9, Value10, Value11, Value12, Value13, Value14, Value15, Value16, Value17, Value18, Value19);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};


// Fallback case for tuples with > 20 items.
template<typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12, typename T13, typename T14, typename T15, typename T16, typename T17, typename T18, typename T19, typename T20, typename... Ts>
class Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, Ts...>
{
  T0 Value0;
  static T0 ElementTypeI(vtkm::internal::IndexTag<0>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T0>& GetImpl(vtkm::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

  T1 Value1;
  static T1 ElementTypeI(vtkm::internal::IndexTag<1>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>)
  {
    return this->Value1;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T1>& GetImpl(vtkm::internal::IndexTag<1>) const
  {
    return this->Value1;
  }

  T2 Value2;
  static T2 ElementTypeI(vtkm::internal::IndexTag<2>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>)
  {
    return this->Value2;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T2>& GetImpl(vtkm::internal::IndexTag<2>) const
  {
    return this->Value2;
  }

  T3 Value3;
  static T3 ElementTypeI(vtkm::internal::IndexTag<3>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>)
  {
    return this->Value3;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T3>& GetImpl(vtkm::internal::IndexTag<3>) const
  {
    return this->Value3;
  }

  T4 Value4;
  static T4 ElementTypeI(vtkm::internal::IndexTag<4>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>)
  {
    return this->Value4;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T4>& GetImpl(vtkm::internal::IndexTag<4>) const
  {
    return this->Value4;
  }

  T5 Value5;
  static T5 ElementTypeI(vtkm::internal::IndexTag<5>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>)
  {
    return this->Value5;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T5>& GetImpl(vtkm::internal::IndexTag<5>) const
  {
    return this->Value5;
  }

  T6 Value6;
  static T6 ElementTypeI(vtkm::internal::IndexTag<6>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>)
  {
    return this->Value6;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T6>& GetImpl(vtkm::internal::IndexTag<6>) const
  {
    return this->Value6;
  }

  T7 Value7;
  static T7 ElementTypeI(vtkm::internal::IndexTag<7>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>)
  {
    return this->Value7;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T7>& GetImpl(vtkm::internal::IndexTag<7>) const
  {
    return this->Value7;
  }

  T8 Value8;
  static T8 ElementTypeI(vtkm::internal::IndexTag<8>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>)
  {
    return this->Value8;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T8>& GetImpl(vtkm::internal::IndexTag<8>) const
  {
    return this->Value8;
  }

  T9 Value9;
  static T9 ElementTypeI(vtkm::internal::IndexTag<9>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>)
  {
    return this->Value9;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T9>& GetImpl(vtkm::internal::IndexTag<9>) const
  {
    return this->Value9;
  }

  T10 Value10;
  static T10 ElementTypeI(vtkm::internal::IndexTag<10>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>)
  {
    return this->Value10;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T10>& GetImpl(vtkm::internal::IndexTag<10>) const
  {
    return this->Value10;
  }

  T11 Value11;
  static T11 ElementTypeI(vtkm::internal::IndexTag<11>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>)
  {
    return this->Value11;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T11>& GetImpl(vtkm::internal::IndexTag<11>) const
  {
    return this->Value11;
  }

  T12 Value12;
  static T12 ElementTypeI(vtkm::internal::IndexTag<12>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T12>& GetImpl(vtkm::internal::IndexTag<12>)
  {
    return this->Value12;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T12>& GetImpl(vtkm::internal::IndexTag<12>) const
  {
    return this->Value12;
  }

  T13 Value13;
  static T13 ElementTypeI(vtkm::internal::IndexTag<13>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T13>& GetImpl(vtkm::internal::IndexTag<13>)
  {
    return this->Value13;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T13>& GetImpl(vtkm::internal::IndexTag<13>) const
  {
    return this->Value13;
  }

  T14 Value14;
  static T14 ElementTypeI(vtkm::internal::IndexTag<14>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T14>& GetImpl(vtkm::internal::IndexTag<14>)
  {
    return this->Value14;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T14>& GetImpl(vtkm::internal::IndexTag<14>) const
  {
    return this->Value14;
  }

  T15 Value15;
  static T15 ElementTypeI(vtkm::internal::IndexTag<15>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T15>& GetImpl(vtkm::internal::IndexTag<15>)
  {
    return this->Value15;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T15>& GetImpl(vtkm::internal::IndexTag<15>) const
  {
    return this->Value15;
  }

  T16 Value16;
  static T16 ElementTypeI(vtkm::internal::IndexTag<16>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T16>& GetImpl(vtkm::internal::IndexTag<16>)
  {
    return this->Value16;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T16>& GetImpl(vtkm::internal::IndexTag<16>) const
  {
    return this->Value16;
  }

  T17 Value17;
  static T17 ElementTypeI(vtkm::internal::IndexTag<17>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T17>& GetImpl(vtkm::internal::IndexTag<17>)
  {
    return this->Value17;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T17>& GetImpl(vtkm::internal::IndexTag<17>) const
  {
    return this->Value17;
  }

  T18 Value18;
  static T18 ElementTypeI(vtkm::internal::IndexTag<18>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T18>& GetImpl(vtkm::internal::IndexTag<18>)
  {
    return this->Value18;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T18>& GetImpl(vtkm::internal::IndexTag<18>) const
  {
    return this->Value18;
  }

  T19 Value19;
  static T19 ElementTypeI(vtkm::internal::IndexTag<19>);
  VTKM_EXEC_CONT vtkm::internal::remove_cvref<T19>& GetImpl(vtkm::internal::IndexTag<19>)
  {
    return this->Value19;
  }
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<T19>& GetImpl(vtkm::internal::IndexTag<19>) const
  {
    return this->Value19;
  }


  // Implement the "extra" objects in a sub-Tuple
  using RemainingValuesType = vtkm::Tuple<T20, Ts...>;
  RemainingValuesType RemainingValues;

  template <vtkm::IdComponent Index>
  static vtkm::TupleElement<Index - 20, RemainingValuesType>
  ElementTypeI(vtkm::internal::IndexTag<Index>);

  template <typename vtkm::IdComponent Index>
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<vtkm::TupleElement<Index - 20, RemainingValuesType>>&
  GetImpl(vtkm::internal::IndexTag<Index>) { return vtkm::Get<Index - 20>(this->RemainingValues); }
  template <typename vtkm::IdComponent Index>
  VTKM_EXEC_CONT const vtkm::internal::remove_cvref<vtkm::TupleElement<Index - 20, RemainingValuesType>>&
  GetImpl(vtkm::internal::IndexTag<Index>) const { return vtkm::Get<Index - 20>(this->RemainingValues); }

  template <vtkm::IdComponent, typename>
  friend struct detail::TupleElementImpl;

public:
  static constexpr vtkm::IdComponent Size =
    21 + static_cast<vtkm::IdComponent>(sizeof...(Ts));
  template <vtkm::IdComponent Index>
  using ElementType = vtkm::TupleElement<Index, Tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, Ts...>>;

  Tuple() = default;
  Tuple(Tuple&&) = default;
  Tuple(const Tuple&) = default;
  ~Tuple() = default;
  Tuple& operator=(Tuple&&) = default;
  Tuple& operator=(const Tuple&) = default;

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9, typename A10, typename A11, typename A12, typename A13, typename A14, typename A15, typename A16, typename A17, typename A18, typename A19, typename... As>
  VTKM_EXEC_CONT Tuple(A0&& a0, A1&& a1, A2&& a2, A3&& a3, A4&& a4, A5&& a5, A6&& a6, A7&& a7, A8&& a8, A9&& a9, A10&& a10, A11&& a11, A12&& a12, A13&& a13, A14&& a14, A15&& a15, A16&& a16, A17&& a17, A18&& a18, A19&& a19, As&&... remainingArgs)
    : Value0(std::forward<A0>(a0))
    , Value1(std::forward<A1>(a1))
    , Value2(std::forward<A2>(a2))
    , Value3(std::forward<A3>(a3))
    , Value4(std::forward<A4>(a4))
    , Value5(std::forward<A5>(a5))
    , Value6(std::forward<A6>(a6))
    , Value7(std::forward<A7>(a7))
    , Value8(std::forward<A8>(a8))
    , Value9(std::forward<A9>(a9))
    , Value10(std::forward<A10>(a10))
    , Value11(std::forward<A11>(a11))
    , Value12(std::forward<A12>(a12))
    , Value13(std::forward<A13>(a13))
    , Value14(std::forward<A14>(a14))
    , Value15(std::forward<A15>(a15))
    , Value16(std::forward<A16>(a16))
    , Value17(std::forward<A17>(a17))
    , Value18(std::forward<A18>(a18))
    , Value19(std::forward<A19>(a19))
    , RemainingValues(std::forward<As>(remainingArgs)...)
  {
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  template <vtkm::IdComponent Index>
  VTKM_EXEC_CONT auto Get() const -> decltype(this->GetImpl(vtkm::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(vtkm::internal::IndexTag<Index>{});
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(this->RemainingValues.Apply(std::forward<Function>(f),
                                            std::forward<Args>(args)...,
                                            this->Value0,
                                            this->Value1,
                                            this->Value2,
                                            this->Value3,
                                            this->Value4,
                                            this->Value5,
                                            this->Value6,
                                            this->Value7,
                                            this->Value8,
                                            this->Value9,
                                            this->Value10,
                                            this->Value11,
                                            this->Value12,
                                            this->Value13,
                                            this->Value14,
                                            this->Value15,
                                            this->Value16,
                                            this->Value17,
                                            this->Value18,
                                            this->Value19))
  {
    return this->RemainingValues.Apply(std::forward<Function>(f),
                                       std::forward<Args>(args)...,
                                       this->Value0,
                                       this->Value1,
                                       this->Value2,
                                       this->Value3,
                                       this->Value4,
                                       this->Value5,
                                       this->Value6,
                                       this->Value7,
                                       this->Value8,
                                       this->Value9,
                                       this->Value10,
                                       this->Value11,
                                       this->Value12,
                                       this->Value13,
                                       this->Value14,
                                       this->Value15,
                                       this->Value16,
                                       this->Value17,
                                       this->Value18,
                                       this->Value19);
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VTKM_EXEC_CONT
  auto Apply(Function&& f, Args&&... args) const
    -> decltype(this->RemainingValues.Apply(std::forward<Function>(f),
                                            std::forward<Args>(args)...,
                                            this->Value0,
                                            this->Value1,
                                            this->Value2,
                                            this->Value3,
                                            this->Value4,
                                            this->Value5,
                                            this->Value6,
                                            this->Value7,
                                            this->Value8,
                                            this->Value9,
                                            this->Value10,
                                            this->Value11,
                                            this->Value12,
                                            this->Value13,
                                            this->Value14,
                                            this->Value15,
                                            this->Value16,
                                            this->Value17,
                                            this->Value18,
                                            this->Value19))
  {
    return this->RemainingValues.Apply(std::forward<Function>(f),
                                       std::forward<Args>(args)...,
                                       this->Value0,
                                       this->Value1,
                                       this->Value2,
                                       this->Value3,
                                       this->Value4,
                                       this->Value5,
                                       this->Value6,
                                       this->Value7,
                                       this->Value8,
                                       this->Value9,
                                       this->Value10,
                                       this->Value11,
                                       this->Value12,
                                       this->Value13,
                                       this->Value14,
                                       this->Value15,
                                       this->Value16,
                                       this->Value17,
                                       this->Value18,
                                       this->Value19);
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f)
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT void ForEach(Function&& f) const
  {
    detail::TupleForEach(*this, std::forward<Function>(f));
  }

  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f)
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
  VTKM_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VTKM_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(detail::TupleTransform(*this, std::forward<Function>(f)))
  {
    return detail::TupleTransform(*this, std::forward<Function>(f));
  }
};

///@}

// clang-format on

} // namespace vtkm

#endif //vtk_m_Tuple_h
