//============================================================================
//  The contents of this file are covered by the Viskores license. See
//  LICENSE.txt for details.
//
//  By contributing to this file, all contributors agree to the Developer
//  Certificate of Origin Version 1.1 (DCO 1.1) as stated in DCO.txt.
//============================================================================

//============================================================================
//  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 viskores_Tuple_h
#define viskores_Tuple_h

#include <viskores/Types.h>

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



namespace viskores
{

///@{
/// \brief Viskores 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 Viskores supports. There are also some implementation
/// details that makes compiling faster for Viskores use. We also provide some methods like `Apply`
/// and `ForEach` that are helpful for several Viskores operations.
///
template <typename... Ts>
class Tuple;

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

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

namespace detail
{

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

} // namespace detail

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

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

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

/// @brief Retrieve the object from a `viskores::Tuple` at the given index.
VISKORES_SUPPRESS_EXEC_WARNINGS
template <viskores::IdComponent Index, typename... Ts>
VISKORES_EXEC_CONT auto Get(const viskores::Tuple<Ts...>& tuple)
#ifndef VISKORES_DOXYGEN_ONLY
  // Breathe (for Sphinx) has problems parsing this declarator id.
  -> decltype(tuple.template Get<Index>())
#endif
{
  return tuple.template Get<Index>();
}

/// @brief Retrieve the object from a `viskores::Tuple` at the given index.
VISKORES_SUPPRESS_EXEC_WARNINGS
template <viskores::IdComponent Index, typename... Ts>
VISKORES_EXEC_CONT auto Get(viskores::Tuple<Ts...>& tuple)
#ifndef VISKORES_DOXYGEN_ONLY
  // Breathe (for Sphinx) has problems parsing this declarator id.
  -> decltype(tuple.template Get<Index>())
#endif
{
  return tuple.template Get<Index>();
}

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

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

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

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

/// @cond NONE
namespace detail
{
struct TupleTransformFunctor
{
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Ts>
  VISKORES_EXEC_CONT auto operator()(Function&& f, Ts&&... args)
    -> decltype(viskores::MakeTuple(f(std::forward<Ts>(args))...))
  {
    return viskores::MakeTuple(f(std::forward<Ts>(args))...);
  }
};

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

} // namespace detail
/// @endcond

/// @brief Call a function with the values of a `viskores::Tuple` as arguments.
///
/// If a `viskores::Tuple<A, B, C>` is given with values `a`, `b`, and `c`, then
/// `f` will be called as `f(a, b, c)`.
///
/// Additional arguments can optionally be given to `viskores::Apply()`. These
/// arguments will be added to the _beginning_ of the arguments to the function.
///
/// The returned value of the function (if any) will be returned from `viskores::Apply()`.
template <typename... Ts, typename Function, typename... Args>
VISKORES_EXEC_CONT auto Apply(const viskores::Tuple<Ts...>& tuple, Function&& f, Args&&... args)
  -> decltype(tuple.Apply(std::forward<Function>(f), std::forward<Args>(args)...))
{
  return tuple.Apply(std::forward<Function>(f), std::forward<Args>(args)...);
}

/// @copydoc Apply
template <typename... Ts, typename Function, typename... Args>
VISKORES_EXEC_CONT auto Apply(viskores::Tuple<Ts...>& tuple, Function&& f, Args&&... args)
  -> decltype(tuple.Apply(std::forward<Function>(f), std::forward<Args>(args)...))
{
  return tuple.Apply(std::forward<Function>(f), std::forward<Args>(args)...);
}

/// @brief Call a function with each value of the given tuple.
///
/// The function calls will be done in the order of the values in the `viskores::Tuple`.
template <typename... Ts, typename Function>
VISKORES_EXEC_CONT void ForEach(const viskores::Tuple<Ts...>& tuple, Function&& f)
{
  return viskores::Apply(tuple, detail::TupleForEachFunctor{}, std::forward<Function>(f));
}

/// @copydoc ForEach
template <typename... Ts, typename Function>
VISKORES_EXEC_CONT void ForEach(viskores::Tuple<Ts...>& tuple, Function&& f)
{
  return viskores::Apply(tuple, detail::TupleForEachFunctor{}, std::forward<Function>(f));
}

///@{
/// @brief Construct a new `viskores::Tuple` by applying a function to each value.
///
/// The `viskores::Transform` function builds a new `viskores::Tuple` by calling a function
/// or functor on each of the items in the given `tuple`. The return value is placed
/// in the corresponding part of the resulting Tuple, and the type is automatically
/// created from the return type of the function.
template <typename TupleType, typename Function>
VISKORES_EXEC_CONT auto Transform(const TupleType&& tuple, Function&& f)
  -> decltype(Apply(tuple, detail::TupleTransformFunctor(), std::forward<Function>(f)))
{
  return Apply(tuple, detail::TupleTransformFunctor(), std::forward<Function>(f));
}

template <typename TupleType, typename Function>
VISKORES_EXEC_CONT auto Transform(TupleType&& tuple, Function&& f)
  -> decltype(Apply(tuple, detail::TupleTransformFunctor(), std::forward<Function>(f)))
{
  return Apply(tuple, detail::TupleTransformFunctor(), std::forward<Function>(f));
}
///@}

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

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&&) const
  {
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT viskores::Tuple<> Transform(Function&&) const
  {
    return viskores::Tuple<>{};
  }
};

// clang-format off

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


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

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

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

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

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

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

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

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
};

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 2;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

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

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

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_EXEC_CONT
  auto Apply(Function&& f, Args&&... args)
    -> decltype(f(std::forward<Args>(args)..., Value0, Value1))
  {
    return f(std::forward<Args>(args)..., Value0, Value1);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
};

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

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 3;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*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(viskores::internal::IndexTag<0>);
  VISKORES_EXEC_CONT viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VISKORES_EXEC_CONT const viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

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

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 4;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*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(viskores::internal::IndexTag<0>);
  VISKORES_EXEC_CONT viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VISKORES_EXEC_CONT const viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

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

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

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 5;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*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(viskores::internal::IndexTag<0>);
  VISKORES_EXEC_CONT viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VISKORES_EXEC_CONT const viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

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

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

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

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 6;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*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(viskores::internal::IndexTag<0>);
  VISKORES_EXEC_CONT viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VISKORES_EXEC_CONT const viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

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

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

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

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

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 7;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*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(viskores::internal::IndexTag<0>);
  VISKORES_EXEC_CONT viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VISKORES_EXEC_CONT const viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

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

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

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

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

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

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 8;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*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(viskores::internal::IndexTag<0>);
  VISKORES_EXEC_CONT viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VISKORES_EXEC_CONT const viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

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

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

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

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

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

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

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 9;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*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(viskores::internal::IndexTag<0>);
  VISKORES_EXEC_CONT viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VISKORES_EXEC_CONT const viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

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

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

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

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

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

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

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

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 10;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename A0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8, typename A9>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*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(viskores::internal::IndexTag<0>);
  VISKORES_EXEC_CONT viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VISKORES_EXEC_CONT const viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

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

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

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

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

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

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

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

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

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 11;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_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>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*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(viskores::internal::IndexTag<0>);
  VISKORES_EXEC_CONT viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VISKORES_EXEC_CONT const viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

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

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

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

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

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

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

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

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

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

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 12;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_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>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*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(viskores::internal::IndexTag<0>);
  VISKORES_EXEC_CONT viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VISKORES_EXEC_CONT const viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

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

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

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

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

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

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

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

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

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

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

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 13;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_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>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*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(viskores::internal::IndexTag<0>);
  VISKORES_EXEC_CONT viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VISKORES_EXEC_CONT const viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 14;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_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>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*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(viskores::internal::IndexTag<0>);
  VISKORES_EXEC_CONT viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VISKORES_EXEC_CONT const viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 15;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_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>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*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(viskores::internal::IndexTag<0>);
  VISKORES_EXEC_CONT viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VISKORES_EXEC_CONT const viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 16;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_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>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*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(viskores::internal::IndexTag<0>);
  VISKORES_EXEC_CONT viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VISKORES_EXEC_CONT const viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 17;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_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>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*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(viskores::internal::IndexTag<0>);
  VISKORES_EXEC_CONT viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VISKORES_EXEC_CONT const viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 18;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_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>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*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(viskores::internal::IndexTag<0>);
  VISKORES_EXEC_CONT viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VISKORES_EXEC_CONT const viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 19;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_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>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*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(viskores::internal::IndexTag<0>);
  VISKORES_EXEC_CONT viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VISKORES_EXEC_CONT const viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

public:
  static constexpr viskores::IdComponent Size = 20;
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_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>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*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(viskores::internal::IndexTag<0>);
  VISKORES_EXEC_CONT viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>)
  {
    return this->Value0;
  }
  VISKORES_EXEC_CONT const viskores::internal::remove_cvref<T0>& GetImpl(viskores::internal::IndexTag<0>) const
  {
    return this->Value0;
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

public:
  static constexpr viskores::IdComponent Size =
    21 + static_cast<viskores::IdComponent>(sizeof...(Ts));
  template <viskores::IdComponent Index>
  using ElementType = viskores::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;

  VISKORES_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>
  VISKORES_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 <viskores::IdComponent Index>
  VISKORES_EXEC_CONT auto Get() -> decltype(this->GetImpl(viskores::internal::IndexTag<Index>{}))
  {
    return this->GetImpl(viskores::internal::IndexTag<Index>{});
  }

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

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function, typename... Args>
  VISKORES_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);
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f)
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT void ForEach(Function&& f) const
  {
    viskores::ForEach(*this, std::forward<Function>(f));
  }

  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f)
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
  VISKORES_SUPPRESS_EXEC_WARNINGS
  template <typename Function>
  VISKORES_EXEC_CONT auto Transform(Function&& f) const
    -> decltype(viskores::Transform(*this, std::forward<Function>(f)))
  {
    return viskores::Transform(*this, std::forward<Function>(f));
  }
};

///@}

// clang-format on

} // namespace viskores

#endif //viskores_Tuple_h
