//============================================================================
//  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 VariantDetail.h.in

#ifndef vtk_m_internal_VariantDetail_h
#define vtk_m_internal_VariantDetail_h

#ifndef vtk_m_internal_Variant_h
#error VariantDetail.h must be included from Variant.h
#endif

#include <vtkm/Types.h>

#include <vtkm/internal/brigand.hpp>

#include <type_traits>



namespace vtkm
{
namespace internal
{
namespace detail
{

template <typename ReturnType>
struct VariantDummyReturn
{
  VTKM_EXEC_CONT static inline ReturnType F() noexcept { return ReturnType{}; }
};
template <>
struct VariantDummyReturn<void>
{
  VTKM_EXEC_CONT static inline void F() noexcept {}
};

template <typename ReturnType, typename Functor, typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(brigand::list<>,
                                                        vtkm::IdComponent,
                                                        Functor&&,
                                                        const void*,
                                                        Args&&...) noexcept
{
  // If we are here, it means we failed to find the appropriate type in a variant
  VTKM_ASSERT(false && "Internal error, bad Variant state.");
  return VariantDummyReturn<ReturnType>::F();
}

// clang-format off

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename T2,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<const T2*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename T2,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<T2*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename T2,
          typename T3,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<const T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<const T3*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename T2,
          typename T3,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<T3*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename T2,
          typename T3,
          typename T4,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<const T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<const T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<const T4*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename T2,
          typename T3,
          typename T4,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<T4*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename T2,
          typename T3,
          typename T4,
          typename T5,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<const T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<const T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<const T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<const T5*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename T2,
          typename T3,
          typename T4,
          typename T5,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<T5*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename T2,
          typename T3,
          typename T4,
          typename T5,
          typename T6,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<const T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<const T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<const T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<const T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<const T6*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename T2,
          typename T3,
          typename T4,
          typename T5,
          typename T6,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<T6*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename T2,
          typename T3,
          typename T4,
          typename T5,
          typename T6,
          typename T7,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<const T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<const T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<const T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<const T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<const T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<const T7*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename T2,
          typename T3,
          typename T4,
          typename T5,
          typename T6,
          typename T7,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<T7*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename T2,
          typename T3,
          typename T4,
          typename T5,
          typename T6,
          typename T7,
          typename T8,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<const T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<const T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<const T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<const T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<const T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<const T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<const T8*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename T2,
          typename T3,
          typename T4,
          typename T5,
          typename T6,
          typename T7,
          typename T8,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<T8*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename T2,
          typename T3,
          typename T4,
          typename T5,
          typename T6,
          typename T7,
          typename T8,
          typename T9,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<const T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<const T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<const T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<const T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<const T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<const T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<const T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<const T9*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename T2,
          typename T3,
          typename T4,
          typename T5,
          typename T6,
          typename T7,
          typename T8,
          typename T9,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<T9*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename T2,
          typename T3,
          typename T4,
          typename T5,
          typename T6,
          typename T7,
          typename T8,
          typename T9,
          typename T10,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<const T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<const T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<const T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<const T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<const T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<const T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<const T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<const T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<const T10*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          typename T0,
          typename T1,
          typename T2,
          typename T3,
          typename T4,
          typename T5,
          typename T6,
          typename T7,
          typename T8,
          typename T9,
          typename T10,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<T10*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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 Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<const T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<const T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<const T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<const T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<const T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<const T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<const T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<const T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<const T10*>(storage), std::forward<Args>(args)...);
    case 11:
      return f(*reinterpret_cast<const T11*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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 Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<T10*>(storage), std::forward<Args>(args)...);
    case 11:
      return f(*reinterpret_cast<T11*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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 Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<const T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<const T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<const T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<const T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<const T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<const T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<const T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<const T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<const T10*>(storage), std::forward<Args>(args)...);
    case 11:
      return f(*reinterpret_cast<const T11*>(storage), std::forward<Args>(args)...);
    case 12:
      return f(*reinterpret_cast<const T12*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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 Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<T10*>(storage), std::forward<Args>(args)...);
    case 11:
      return f(*reinterpret_cast<T11*>(storage), std::forward<Args>(args)...);
    case 12:
      return f(*reinterpret_cast<T12*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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 Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<const T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<const T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<const T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<const T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<const T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<const T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<const T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<const T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<const T10*>(storage), std::forward<Args>(args)...);
    case 11:
      return f(*reinterpret_cast<const T11*>(storage), std::forward<Args>(args)...);
    case 12:
      return f(*reinterpret_cast<const T12*>(storage), std::forward<Args>(args)...);
    case 13:
      return f(*reinterpret_cast<const T13*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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 Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<T10*>(storage), std::forward<Args>(args)...);
    case 11:
      return f(*reinterpret_cast<T11*>(storage), std::forward<Args>(args)...);
    case 12:
      return f(*reinterpret_cast<T12*>(storage), std::forward<Args>(args)...);
    case 13:
      return f(*reinterpret_cast<T13*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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 Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<const T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<const T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<const T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<const T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<const T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<const T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<const T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<const T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<const T10*>(storage), std::forward<Args>(args)...);
    case 11:
      return f(*reinterpret_cast<const T11*>(storage), std::forward<Args>(args)...);
    case 12:
      return f(*reinterpret_cast<const T12*>(storage), std::forward<Args>(args)...);
    case 13:
      return f(*reinterpret_cast<const T13*>(storage), std::forward<Args>(args)...);
    case 14:
      return f(*reinterpret_cast<const T14*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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 Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<T10*>(storage), std::forward<Args>(args)...);
    case 11:
      return f(*reinterpret_cast<T11*>(storage), std::forward<Args>(args)...);
    case 12:
      return f(*reinterpret_cast<T12*>(storage), std::forward<Args>(args)...);
    case 13:
      return f(*reinterpret_cast<T13*>(storage), std::forward<Args>(args)...);
    case 14:
      return f(*reinterpret_cast<T14*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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 Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<const T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<const T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<const T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<const T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<const T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<const T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<const T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<const T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<const T10*>(storage), std::forward<Args>(args)...);
    case 11:
      return f(*reinterpret_cast<const T11*>(storage), std::forward<Args>(args)...);
    case 12:
      return f(*reinterpret_cast<const T12*>(storage), std::forward<Args>(args)...);
    case 13:
      return f(*reinterpret_cast<const T13*>(storage), std::forward<Args>(args)...);
    case 14:
      return f(*reinterpret_cast<const T14*>(storage), std::forward<Args>(args)...);
    case 15:
      return f(*reinterpret_cast<const T15*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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 Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<T10*>(storage), std::forward<Args>(args)...);
    case 11:
      return f(*reinterpret_cast<T11*>(storage), std::forward<Args>(args)...);
    case 12:
      return f(*reinterpret_cast<T12*>(storage), std::forward<Args>(args)...);
    case 13:
      return f(*reinterpret_cast<T13*>(storage), std::forward<Args>(args)...);
    case 14:
      return f(*reinterpret_cast<T14*>(storage), std::forward<Args>(args)...);
    case 15:
      return f(*reinterpret_cast<T15*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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 Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<const T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<const T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<const T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<const T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<const T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<const T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<const T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<const T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<const T10*>(storage), std::forward<Args>(args)...);
    case 11:
      return f(*reinterpret_cast<const T11*>(storage), std::forward<Args>(args)...);
    case 12:
      return f(*reinterpret_cast<const T12*>(storage), std::forward<Args>(args)...);
    case 13:
      return f(*reinterpret_cast<const T13*>(storage), std::forward<Args>(args)...);
    case 14:
      return f(*reinterpret_cast<const T14*>(storage), std::forward<Args>(args)...);
    case 15:
      return f(*reinterpret_cast<const T15*>(storage), std::forward<Args>(args)...);
    case 16:
      return f(*reinterpret_cast<const T16*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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 Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<T10*>(storage), std::forward<Args>(args)...);
    case 11:
      return f(*reinterpret_cast<T11*>(storage), std::forward<Args>(args)...);
    case 12:
      return f(*reinterpret_cast<T12*>(storage), std::forward<Args>(args)...);
    case 13:
      return f(*reinterpret_cast<T13*>(storage), std::forward<Args>(args)...);
    case 14:
      return f(*reinterpret_cast<T14*>(storage), std::forward<Args>(args)...);
    case 15:
      return f(*reinterpret_cast<T15*>(storage), std::forward<Args>(args)...);
    case 16:
      return f(*reinterpret_cast<T16*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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 Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<const T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<const T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<const T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<const T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<const T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<const T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<const T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<const T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<const T10*>(storage), std::forward<Args>(args)...);
    case 11:
      return f(*reinterpret_cast<const T11*>(storage), std::forward<Args>(args)...);
    case 12:
      return f(*reinterpret_cast<const T12*>(storage), std::forward<Args>(args)...);
    case 13:
      return f(*reinterpret_cast<const T13*>(storage), std::forward<Args>(args)...);
    case 14:
      return f(*reinterpret_cast<const T14*>(storage), std::forward<Args>(args)...);
    case 15:
      return f(*reinterpret_cast<const T15*>(storage), std::forward<Args>(args)...);
    case 16:
      return f(*reinterpret_cast<const T16*>(storage), std::forward<Args>(args)...);
    case 17:
      return f(*reinterpret_cast<const T17*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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 Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<T10*>(storage), std::forward<Args>(args)...);
    case 11:
      return f(*reinterpret_cast<T11*>(storage), std::forward<Args>(args)...);
    case 12:
      return f(*reinterpret_cast<T12*>(storage), std::forward<Args>(args)...);
    case 13:
      return f(*reinterpret_cast<T13*>(storage), std::forward<Args>(args)...);
    case 14:
      return f(*reinterpret_cast<T14*>(storage), std::forward<Args>(args)...);
    case 15:
      return f(*reinterpret_cast<T15*>(storage), std::forward<Args>(args)...);
    case 16:
      return f(*reinterpret_cast<T16*>(storage), std::forward<Args>(args)...);
    case 17:
      return f(*reinterpret_cast<T17*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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 Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<const T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<const T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<const T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<const T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<const T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<const T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<const T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<const T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<const T10*>(storage), std::forward<Args>(args)...);
    case 11:
      return f(*reinterpret_cast<const T11*>(storage), std::forward<Args>(args)...);
    case 12:
      return f(*reinterpret_cast<const T12*>(storage), std::forward<Args>(args)...);
    case 13:
      return f(*reinterpret_cast<const T13*>(storage), std::forward<Args>(args)...);
    case 14:
      return f(*reinterpret_cast<const T14*>(storage), std::forward<Args>(args)...);
    case 15:
      return f(*reinterpret_cast<const T15*>(storage), std::forward<Args>(args)...);
    case 16:
      return f(*reinterpret_cast<const T16*>(storage), std::forward<Args>(args)...);
    case 17:
      return f(*reinterpret_cast<const T17*>(storage), std::forward<Args>(args)...);
    case 18:
      return f(*reinterpret_cast<const T18*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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 Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<T10*>(storage), std::forward<Args>(args)...);
    case 11:
      return f(*reinterpret_cast<T11*>(storage), std::forward<Args>(args)...);
    case 12:
      return f(*reinterpret_cast<T12*>(storage), std::forward<Args>(args)...);
    case 13:
      return f(*reinterpret_cast<T13*>(storage), std::forward<Args>(args)...);
    case 14:
      return f(*reinterpret_cast<T14*>(storage), std::forward<Args>(args)...);
    case 15:
      return f(*reinterpret_cast<T15*>(storage), std::forward<Args>(args)...);
    case 16:
      return f(*reinterpret_cast<T16*>(storage), std::forward<Args>(args)...);
    case 17:
      return f(*reinterpret_cast<T17*>(storage), std::forward<Args>(args)...);
    case 18:
      return f(*reinterpret_cast<T18*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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 Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<const T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<const T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<const T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<const T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<const T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<const T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<const T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<const T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<const T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<const T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<const T10*>(storage), std::forward<Args>(args)...);
    case 11:
      return f(*reinterpret_cast<const T11*>(storage), std::forward<Args>(args)...);
    case 12:
      return f(*reinterpret_cast<const T12*>(storage), std::forward<Args>(args)...);
    case 13:
      return f(*reinterpret_cast<const T13*>(storage), std::forward<Args>(args)...);
    case 14:
      return f(*reinterpret_cast<const T14*>(storage), std::forward<Args>(args)...);
    case 15:
      return f(*reinterpret_cast<const T15*>(storage), std::forward<Args>(args)...);
    case 16:
      return f(*reinterpret_cast<const T16*>(storage), std::forward<Args>(args)...);
    case 17:
      return f(*reinterpret_cast<const T17*>(storage), std::forward<Args>(args)...);
    case 18:
      return f(*reinterpret_cast<const T18*>(storage), std::forward<Args>(args)...);
    case 19:
      return f(*reinterpret_cast<const T19*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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 Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  switch (index)
  {
    case 0:
      return f(*reinterpret_cast<T0*>(storage), std::forward<Args>(args)...);
    case 1:
      return f(*reinterpret_cast<T1*>(storage), std::forward<Args>(args)...);
    case 2:
      return f(*reinterpret_cast<T2*>(storage), std::forward<Args>(args)...);
    case 3:
      return f(*reinterpret_cast<T3*>(storage), std::forward<Args>(args)...);
    case 4:
      return f(*reinterpret_cast<T4*>(storage), std::forward<Args>(args)...);
    case 5:
      return f(*reinterpret_cast<T5*>(storage), std::forward<Args>(args)...);
    case 6:
      return f(*reinterpret_cast<T6*>(storage), std::forward<Args>(args)...);
    case 7:
      return f(*reinterpret_cast<T7*>(storage), std::forward<Args>(args)...);
    case 8:
      return f(*reinterpret_cast<T8*>(storage), std::forward<Args>(args)...);
    case 9:
      return f(*reinterpret_cast<T9*>(storage), std::forward<Args>(args)...);
    case 10:
      return f(*reinterpret_cast<T10*>(storage), std::forward<Args>(args)...);
    case 11:
      return f(*reinterpret_cast<T11*>(storage), std::forward<Args>(args)...);
    case 12:
      return f(*reinterpret_cast<T12*>(storage), std::forward<Args>(args)...);
    case 13:
      return f(*reinterpret_cast<T13*>(storage), std::forward<Args>(args)...);
    case 14:
      return f(*reinterpret_cast<T14*>(storage), std::forward<Args>(args)...);
    case 15:
      return f(*reinterpret_cast<T15*>(storage), std::forward<Args>(args)...);
    case 16:
      return f(*reinterpret_cast<T16*>(storage), std::forward<Args>(args)...);
    case 17:
      return f(*reinterpret_cast<T17*>(storage), std::forward<Args>(args)...);
    case 18:
      return f(*reinterpret_cast<T18*>(storage), std::forward<Args>(args)...);
    case 19:
      return f(*reinterpret_cast<T19*>(storage), std::forward<Args>(args)...);
    default:
      // If we are here, it means we failed to find the appropriate type in a variant
      VTKM_ASSERT(false && "Internal error, bad Variant state.");
      return VariantDummyReturn<ReturnType>::F();
  }
}

//clang-format on

// Recurse for cases where Variant has more than 20 types
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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... RemainingT,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, RemainingT...>,
  vtkm::IdComponent index,
  Functor&& f,
  const void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  if (index < 20)
  {
    return VariantCastAndCallImpl<ReturnType>(
      brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>{},
      index,
      f,
      storage,
      args...);
  }
  else
  {
    return VariantCastAndCallImpl<ReturnType>(
      brigand::list<T20, RemainingT...>{}, index - 20, f, storage, args...);
  }
}

VTKM_SUPPRESS_EXEC_WARNINGS
template <typename ReturnType,
          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... RemainingT,
          typename Functor,
          typename... Args>
VTKM_EXEC_CONT inline ReturnType VariantCastAndCallImpl(
  brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, RemainingT...>,
  vtkm::IdComponent index,
  Functor&& f,
  void* storage,
  Args&&... args) noexcept(noexcept(f(std::declval<const T0&>(), args...)))
{
  if (index < 20)
  {
    return VariantCastAndCallImpl<ReturnType>(
      brigand::list<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19>{},
      index,
      f,
      storage,
      args...);
  }
  else
  {
    return VariantCastAndCallImpl<ReturnType>(
      brigand::list<T20, RemainingT...>{}, index - 20, f, storage, args...);
  }
}

}
}
} // vtkm::internal::detail

#endif //vtk_m_internal_VariantDetail_h
