Commit 647bc94f authored by Kenneth Moreland's avatar Kenneth Moreland
Browse files

Reduce the number of lines required to implement Variant::CastAndCall

parent 991eeba9
......@@ -179,11 +179,8 @@ struct VariantStorageImpl
-> decltype(f(std::declval<const TypeAt<0>&>(), args...))
{
VTKM_ASSERT(this->IsValid());
return detail::VariantCastAndCallImpl(vtkm::ListSize<vtkm::List<Ts...>>{},
this->GetIndex(),
std::forward<Functor>(f),
this->Storage,
std::forward<Args>(args)...);
return detail::VariantCastAndCallImpl(
this->GetIndex(), std::forward<Functor>(f), this->Storage, std::forward<Args>(args)...);
}
template <typename Functor, typename... Args>
......@@ -192,11 +189,8 @@ struct VariantStorageImpl
-> decltype(f(std::declval<TypeAt<0>&>(), args...))
{
VTKM_ASSERT(this->IsValid());
return detail::VariantCastAndCallImpl(vtkm::ListSize<vtkm::List<Ts...>>{},
this->GetIndex(),
std::forward<Functor>(f),
this->Storage,
std::forward<Args>(args)...);
return detail::VariantCastAndCallImpl(
this->GetIndex(), std::forward<Functor>(f), this->Storage, std::forward<Args>(args)...);
}
};
......@@ -466,11 +460,7 @@ public:
{
VTKM_ASSERT(this->IsValid());
return detail::VariantCastAndCallImpl(
std::integral_constant<vtkm::IdComponent, NumberOfTypes>{},
this->GetIndex(),
std::forward<Functor>(f),
this->Storage,
std::forward<Args>(args)...);
this->GetIndex(), std::forward<Functor>(f), this->Storage, std::forward<Args>(args)...);
}
template <typename Functor, typename... Args>
......@@ -480,11 +470,7 @@ public:
{
VTKM_ASSERT(this->IsValid());
return detail::VariantCastAndCallImpl(
std::integral_constant<vtkm::IdComponent, NumberOfTypes>{},
this->GetIndex(),
std::forward<Functor>(f),
this->Storage,
std::forward<Args>(args)...);
this->GetIndex(), std::forward<Functor>(f), this->Storage, std::forward<Args>(args)...);
}
/// Destroys any object the Variant is holding and sets the Variant to an invalid state. This
......
......@@ -306,6 +306,7 @@ union VariantUnionTD<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
T17 V17;
T18 V18;
T19 V19;
vtkm::internal::NullType Remaining;
VTK_M_DEVICE VariantUnionTD(vtkm::internal::NullType) { }
VariantUnionTD() = default;
......@@ -334,6 +335,7 @@ union VariantUnionNTD<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13
T17 V17;
T18 V18;
T19 V19;
vtkm::internal::NullType Remaining;
VTK_M_DEVICE VariantUnionNTD(vtkm::internal::NullType) { }
VariantUnionNTD() = default;
......@@ -343,7 +345,6 @@ union VariantUnionNTD<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13
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>
union VariantUnionTD<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, Ts...>
{
vtkm::internal::NullType Dummy;
T0 V0;
T1 V1;
T2 V2;
......@@ -373,7 +374,6 @@ union VariantUnionTD<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
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>
union VariantUnionNTD<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, Ts...>
{
vtkm::internal::NullType Dummy;
T0 V0;
T1 V1;
T2 V2;
......@@ -728,892 +728,201 @@ VTK_M_DEVICE auto VariantUnionGet(UnionType& storage) noexcept
return VariantUnionGetImpl<I, typename std::decay<UnionType>::type>::Get(storage);
}
//clang-format on
// --------------------------------------------------------------------------------
// Internal implementation of CastAndCall for Variant
template <typename Functor,
typename UnionType,
typename... Args>
VTK_M_DEVICE inline auto VariantCastAndCallImpl(
std::integral_constant<vtkm::IdComponent, 1>,
vtkm::IdComponent index,
Functor&& f,
UnionType& storage,
Args&&... args) noexcept(noexcept(f(storage.V0, args...)))
-> decltype(f(storage.V0, args...))
{
switch (index)
{
case 0:
return f(storage.V0, 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<decltype(f(storage.V0, args...))>::F();
}
}
template <typename Functor,
typename UnionType,
typename... Args>
VTK_M_DEVICE inline auto VariantCastAndCallImpl(
std::integral_constant<vtkm::IdComponent, 2>,
vtkm::IdComponent index,
Functor&& f,
UnionType& storage,
Args&&... args) noexcept(noexcept(f(storage.V0, args...)))
-> decltype(f(storage.V0, args...))
{
switch (index)
{
case 0:
return f(storage.V0, std::forward<Args>(args)...);
case 1:
return f(storage.V1, 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<decltype(f(storage.V0, args...))>::F();
}
}
template <typename Functor,
typename UnionType,
typename... Args>
VTK_M_DEVICE inline auto VariantCastAndCallImpl(
std::integral_constant<vtkm::IdComponent, 3>,
vtkm::IdComponent index,
Functor&& f,
UnionType& storage,
Args&&... args) noexcept(noexcept(f(storage.V0, args...)))
-> decltype(f(storage.V0, args...))
{
switch (index)
{
case 0:
return f(storage.V0, std::forward<Args>(args)...);
case 1:
return f(storage.V1, std::forward<Args>(args)...);
case 2:
return f(storage.V2, 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<decltype(f(storage.V0, args...))>::F();
}
}
template <typename Functor,
typename UnionType,
typename... Args>
VTK_M_DEVICE inline auto VariantCastAndCallImpl(
std::integral_constant<vtkm::IdComponent, 4>,
vtkm::IdComponent index,
Functor&& f,
UnionType& storage,
Args&&... args) noexcept(noexcept(f(storage.V0, args...)))
-> decltype(f(storage.V0, args...))
{
switch (index)
{
case 0:
return f(storage.V0, std::forward<Args>(args)...);
case 1:
return f(storage.V1, std::forward<Args>(args)...);
case 2:
return f(storage.V2, std::forward<Args>(args)...);
case 3:
return f(storage.V3, 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<decltype(f(storage.V0, args...))>::F();
}
}
template <typename Functor,
typename UnionType,
typename... Args>
VTK_M_DEVICE inline auto VariantCastAndCallImpl(
std::integral_constant<vtkm::IdComponent, 5>,
vtkm::IdComponent index,
Functor&& f,
UnionType& storage,
Args&&... args) noexcept(noexcept(f(storage.V0, args...)))
-> decltype(f(storage.V0, args...))
{
switch (index)
{
case 0:
return f(storage.V0, std::forward<Args>(args)...);
case 1:
return f(storage.V1, std::forward<Args>(args)...);
case 2:
return f(storage.V2, std::forward<Args>(args)...);
case 3:
return f(storage.V3, std::forward<Args>(args)...);
case 4:
return f(storage.V4, 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<decltype(f(storage.V0, args...))>::F();
}
}
template <typename Functor,
typename UnionType,
typename... Args>
VTK_M_DEVICE inline auto VariantCastAndCallImpl(
std::integral_constant<vtkm::IdComponent, 6>,
vtkm::IdComponent index,
Functor&& f,
UnionType& storage,
Args&&... args) noexcept(noexcept(f(storage.V0, args...)))
-> decltype(f(storage.V0, args...))
{
switch (index)
{
case 0:
return f(storage.V0, std::forward<Args>(args)...);
case 1:
return f(storage.V1, std::forward<Args>(args)...);
case 2:
return f(storage.V2, std::forward<Args>(args)...);
case 3:
return f(storage.V3, std::forward<Args>(args)...);
case 4:
return f(storage.V4, std::forward<Args>(args)...);
case 5:
return f(storage.V5, 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<decltype(f(storage.V0, args...))>::F();
}
}
template <typename Functor,
typename UnionType,
typename... Args>
VTK_M_DEVICE inline auto VariantCastAndCallImpl(
std::integral_constant<vtkm::IdComponent, 7>,
vtkm::IdComponent index,
Functor&& f,
UnionType& storage,
Args&&... args) noexcept(noexcept(f(storage.V0, args...)))
-> decltype(f(storage.V0, args...))
{
switch (index)
{
case 0:
return f(storage.V0, std::forward<Args>(args)...);
case 1:
return f(storage.V1, std::forward<Args>(args)...);
case 2:
return f(storage.V2, std::forward<Args>(args)...);
case 3:
return f(storage.V3, std::forward<Args>(args)...);
case 4:
return f(storage.V4, std::forward<Args>(args)...);
case 5:
return f(storage.V5, std::forward<Args>(args)...);
case 6:
return f(storage.V6, 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<decltype(f(storage.V0, args...))>::F();
}
}
template <typename Functor,
typename UnionType,
typename... Args>
VTK_M_DEVICE inline auto VariantCastAndCallImpl(
std::integral_constant<vtkm::IdComponent, 8>,
vtkm::IdComponent index,
Functor&& f,
UnionType& storage,
Args&&... args) noexcept(noexcept(f(storage.V0, args...)))
-> decltype(f(storage.V0, args...))
{
switch (index)
{
case 0:
return f(storage.V0, std::forward<Args>(args)...);
case 1:
return f(storage.V1, std::forward<Args>(args)...);
case 2:
return f(storage.V2, std::forward<Args>(args)...);
case 3:
return f(storage.V3, std::forward<Args>(args)...);
case 4:
return f(storage.V4, std::forward<Args>(args)...);
case 5:
return f(storage.V5, std::forward<Args>(args)...);
case 6:
return f(storage.V6, std::forward<Args>(args)...);
case 7:
return f(storage.V7, 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<decltype(f(storage.V0, args...))>::F();
}
}
template <typename Functor,
typename UnionType,
typename... Args>
VTK_M_DEVICE inline auto VariantCastAndCallImpl(
std::integral_constant<vtkm::IdComponent, 9>,
vtkm::IdComponent index,
Functor&& f,
UnionType& storage,
Args&&... args) noexcept(noexcept(f(storage.V0, args...)))
-> decltype(f(storage.V0, args...))
{
switch (index)
{
case 0:
return f(storage.V0, std::forward<Args>(args)...);
case 1:
return f(storage.V1, std::forward<Args>(args)...);
case 2:
return f(storage.V2, std::forward<Args>(args)...);
case 3:
return f(storage.V3, std::forward<Args>(args)...);
case 4:
return f(storage.V4, std::forward<Args>(args)...);
case 5:
return f(storage.V5, std::forward<Args>(args)...);
case 6:
return f(storage.V6, std::forward<Args>(args)...);
case 7:
return f(storage.V7, std::forward<Args>(args)...);
case 8:
return f(storage.V8, 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<decltype(f(storage.V0, args...))>::F();
}
}
template <typename Functor,
typename UnionType,
typename... Args>
VTK_M_DEVICE inline auto VariantCastAndCallImpl(
std::integral_constant<vtkm::IdComponent, 10>,
vtkm::IdComponent index,
Functor&& f,
UnionType& storage,
Args&&... args) noexcept(noexcept(f(storage.V0, args...)))
-> decltype(f(storage.V0, args...))
{
switch (index)
{
case 0:
return f(storage.V0, std::forward<Args>(args)...);
case 1:
return f(storage.V1, std::forward<Args>(args)...);
case 2:
return f(storage.V2, std::forward<Args>(args)...);
case 3:
return f(storage.V3, std::forward<Args>(args)...);
case 4:
return f(storage.V4, std::forward<Args>(args)...);
case 5:
return f(storage.V5, std::forward<Args>(args)...);
case 6:
return f(storage.V6, std::forward<Args>(args)...);
case 7:
return f(storage.V7, std::forward<Args>(args)...);
case 8:
return f(storage.V8, std::forward<Args>(args)...);
case 9:
return f(storage.V9, 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<decltype(f(storage.V0, args...))>::F();
}
}
template <typename Functor,
typename UnionType,
typename... Args>
VTK_M_DEVICE inline auto VariantCastAndCallImpl(
std::integral_constant<vtkm::IdComponent, 11>,
vtkm::IdComponent index,
Functor&& f,
UnionType& storage,
Args&&... args) noexcept(noexcept(f(storage.V0, args...)))
-> decltype(f(storage.V0, args...))
{
switch (index)
{
case 0:
return f(storage.V0, std::forward<Args>(args)...);
case 1:
return f(storage.V1, std::forward<Args>(args)...);
case 2:
return f(storage.V2, std::forward<Args>(args)...);
case 3:
return f(storage.V3, std::forward<Args>(args)...);
case 4:
return f(storage.V4, std::forward<Args>(args)...);
case 5:
return f(storage.V5, std::forward<Args>(args)...);
case 6:
return f(storage.V6, std::forward<Args>(args)...);
case 7:
return f(storage.V7, std::forward<Args>(args)...);
case 8:
return f(storage.V8, std::forward<Args>(args)...);
case 9:
return f(storage.V9, std::forward<Args>(args)...);
case 10:
return f(storage.V10, 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<decltype(f(storage.V0, args...))>::F();
}
}
template <typename Functor,
typename UnionType,
typename... Args>
VTK_M_DEVICE inline auto VariantCastAndCallImpl(
std::integral_constant<vtkm::IdComponent, 12>,
vtkm::IdComponent index,
Functor&& f,
UnionType& storage,
Args&&... args) noexcept(noexcept(f(storage.V0, args...)))
-> decltype(f(storage.V0, args...))
{
switch (index)
{
case 0:
return f(storage.V0, std::forward<Args>(args)...);
case 1:
return f(storage.V1, std::forward<Args>(args)...);
case 2:
return f(storage.V2, std::forward<Args>(args)...);
case 3:
return f(storage.V3, std::forward<Args>(args)...);
case 4:
return f(storage.V4, std::forward<Args>(args)...);
case 5:
return f(storage.V5, std::forward<Args>(args)...);
case 6:
return f(storage.V6, std::forward<Args>(args)...);
case 7:
return f(storage.V7, std::forward<Args>(args)...);
case 8:
return f(storage.V8, std::forward<Args>(args)...);
case 9:
return f(storage.V9, std::forward<Args>(args)...);
case 10:
return f(storage.V10, std::forward<Args>(args)...);
case 11:
return f(storage.V11, 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<decltype(f(storage.V0, args...))>::F();
}
}
template <typename Functor,
typename UnionType,
typename... Args>
VTK_M_DEVICE inline auto VariantCastAndCallImpl(
std::integral_constant<vtkm::IdComponent, 13>,
vtkm::IdComponent index,
Functor&& f,
UnionType& storage,
Args&&... args) noexcept(noexcept(f(storage.V0, args...)))
-> decltype(f(storage.V0, args...))
{
switch (index)
{
case 0:
return f(storage.V0, std::forward<Args>(args)...);
case 1:
return f(storage.V1, std::forward<Args>(args)...);
case 2:
return f(storage.V2, std::forward<Args>(args)...);
case 3:
return f(storage.V3, std::forward<Args>(args)...);
case 4:
return f(storage.V4, std::forward<Args>(args)...);
case 5:
return f(storage.V5, std::forward<Args>(args)...);
case 6:
return f(storage.V6, std::forward<Args>(args)...);
case 7:
return f(storage.V7, std::forward<Args>(args)...);
case 8:
return f(storage.V8, std::forward<Args>(args)...);
case 9:
return f(storage.V9, std::forward<Args>(args)...);
case 10:
return f(storage.V10, std::forward<Args>(args)...);
case 11:
return f(storage.V11, std::forward<Args>(args)...);
case 12:
return f(storage.V12, 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<decltype(f(storage.V0, args...))>::F();
}
}
template <typename Functor,
typename UnionType,
typename... Args>
VTK_M_DEVICE inline auto VariantCastAndCallImpl(
std::integral_constant<vtkm::IdComponent, 14>,
vtkm::IdComponent index,
Functor&& f,
UnionType& storage,
Args&&... args) noexcept(noexcept(f(storage.V0, args...)))
-> decltype(f(storage.V0, args...))
{
switch (index)
{
case 0:
return f(storage.V0, std::forward<Args>(args)...);
case 1:
return f(storage.V1, std::forward<Args>(args)...);
case 2:
return f(storage.V2, std::forward<Args>(args)...);
case 3:
return f(storage.V3, std::forward<Args>(args)...);
case 4:
return f(storage.V4, std::forward<Args>(args)...);
case 5:
return f(storage.V5, std::forward<Args>(args)...);
case 6:
return f(storage.V6, std::forward<Args>(args)...);
case 7:
return f(storage.V7, std::forward<Args>(args)...);
case 8:
return f(storage.V8, std::forward<Args>(args)...);
case 9:
return f(storage.V9, std::forward<Args>(args)...);
case 10:
return f(storage.V10, std::forward<Args>(args)...);
case 11:
return f(storage.V11, std::forward<Args>(args)...);
case 12:
return f(storage.V12, std::forward<Args>(args)...);
case 13:
return f(storage.V13, 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<decltype(f(storage.V0, args...))>::F();
}
}
template <typename Functor,