Consolidate dynamic_cast calls.

Previously in DynamicArrayHandle the dynamic_cast was contained in a
method that was reimplemented for every different instance of
DynamicArrayHandleBase. Change that to put the dynamic_cast in a
function outside of the class so that there is only one implementation
created per ArrayHandle type.

Similarly, DynamicCellSet had its dynamic_cast in a method plus there
was a second version in the functors used for the CastAndCall method.
Consolidate all of these into a function outside of either much like
DynamicArrayHandle.
This commit is contained in:
Kenneth Moreland 2016-01-14 10:56:20 -07:00
parent 61ed34e154
commit 92d2ad6a72
2 changed files with 98 additions and 57 deletions

@ -121,6 +121,39 @@ struct DynamicArrayHandleCopyHelper {
}
};
// A simple function to downcast an ArrayHandle encapsulated in a
// PolymorphicArrayHandleContainerBase to the given type of ArrayHandle. If the
// conversion cannot be done, NULL is returned.
template<typename Type, typename Storage>
VTKM_CONT_EXPORT
vtkm::cont::ArrayHandle<Type,Storage> *
DynamicArrayHandleTryCast(
vtkm::cont::detail::PolymorphicArrayHandleContainerBase *arrayContainer)
{
vtkm::cont::detail::PolymorphicArrayHandleContainer<Type,Storage> *
downcastContainer = dynamic_cast<
vtkm::cont::detail::PolymorphicArrayHandleContainer<Type,Storage> *>(
arrayContainer);
if (downcastContainer != NULL)
{
return &downcastContainer->Array;
}
else
{
return NULL;
}
}
template<typename Type, typename Storage>
VTKM_CONT_EXPORT
vtkm::cont::ArrayHandle<Type,Storage> *
DynamicArrayHandleTryCast(
boost::shared_ptr<vtkm::cont::detail::PolymorphicArrayHandleContainerBase>
arrayContainer)
{
return detail::DynamicArrayHandleTryCast<Type,Storage>(arrayContainer.get());
}
} // namespace detail
/// \brief Holds an array handle without having to specify template parameters.
@ -200,7 +233,9 @@ public:
template<typename Type, typename Storage>
VTKM_CONT_EXPORT
bool IsTypeAndStorage(Type = Type(), Storage = Storage()) const {
return (this->TryCastContainer<Type,Storage>() != NULL);
return (
detail::DynamicArrayHandleTryCast<Type,Storage>(this->ArrayContainer)
!= NULL);
}
/// Returns true if this array matches the array handle type passed in.
@ -223,13 +258,13 @@ public:
VTKM_CONT_EXPORT
vtkm::cont::ArrayHandle<Type, Storage>
CastToArrayHandle(Type = Type(), Storage = Storage()) const {
vtkm::cont::detail::PolymorphicArrayHandleContainer<Type,Storage> *container
= this->TryCastContainer<Type,Storage>();
if (container == NULL)
vtkm::cont::ArrayHandle<Type, Storage> *downcastArray =
detail::DynamicArrayHandleTryCast<Type,Storage>(this->ArrayContainer);
if (downcastArray == NULL)
{
throw vtkm::cont::ErrorControlBadValue("Bad cast of dynamic array.");
}
return container->Array;
return *downcastArray;
}
/// Given a refernce to an ArrayHandle object, casts this array to the
@ -348,16 +383,6 @@ private:
ArrayContainer;
friend struct detail::DynamicArrayHandleCopyHelper;
template<typename Type, typename Storage>
VTKM_CONT_EXPORT
vtkm::cont::detail::PolymorphicArrayHandleContainer<Type,Storage> *
TryCastContainer() const {
return
dynamic_cast<
vtkm::cont::detail::PolymorphicArrayHandleContainer<Type,Storage> *>(
this->ArrayContainer.get());
}
};
typedef vtkm::cont::DynamicArrayHandleBase<

@ -56,6 +56,39 @@ struct DynamicCellSetCopyHelper {
}
};
// A simple function to downcast a CellSet encapsulated in a
// SimplePolymorphicContainerBase to the given subclass of CellSet. If the
// conversion cannot be done, NULL is returned.
template<typename CellSetType>
VTKM_CONT_EXPORT
CellSetType *
DynamicCellSetTryCast(
vtkm::cont::internal::SimplePolymorphicContainerBase *cellSetContainer)
{
vtkm::cont::internal::SimplePolymorphicContainer<CellSetType> *
downcastContainer = dynamic_cast<
vtkm::cont::internal::SimplePolymorphicContainer<CellSetType> *>(
cellSetContainer);
if (downcastContainer != NULL)
{
return &downcastContainer->Item;
}
else
{
return NULL;
}
}
template<typename CellSetType>
VTKM_CONT_EXPORT
CellSetType *
DynamicCellSetTryCast(
boost::shared_ptr<vtkm::cont::internal::SimplePolymorphicContainerBase>
cellSetContainer)
{
return detail::DynamicCellSetTryCast<CellSetType>(cellSetContainer.get());
}
} // namespace detail
/// \brief Holds a cell set without having to specify concrete type.
@ -133,7 +166,8 @@ public:
template<typename CellSetType>
VTKM_CONT_EXPORT
bool IsType(CellSetType = CellSetType()) const {
return (this->TryCast<CellSetType>() != NULL);
return (detail::DynamicCellSetTryCast<CellSetType>(this->CellSetContainer)
!= NULL);
}
/// Returns the contained cell set as the abstract \c CellSet type.
@ -151,24 +185,24 @@ public:
template<typename CellSetType>
VTKM_CONT_EXPORT
const CellSetType &CastTo(CellSetType = CellSetType()) const {
const vtkm::cont::internal::SimplePolymorphicContainer<CellSetType> *
container = this->TryCast<CellSetType>();
if (container == NULL)
const CellSetType *cellSet =
detail::DynamicCellSetTryCast<CellSetType>(this->CellSetContainer);
if (cellSet == NULL)
{
throw vtkm::cont::ErrorControlBadValue("Bad cast of dynamic cell set.");
}
return container->Item;
return *cellSet;
}
template<typename CellSetType>
VTKM_CONT_EXPORT
CellSetType &CastTo(CellSetType = CellSetType()) {
vtkm::cont::internal::SimplePolymorphicContainer<CellSetType> *
container = this->TryCast<CellSetType>();
if (container == NULL)
CellSetType *cellSet =
detail::DynamicCellSetTryCast<CellSetType>(this->CellSetContainer);
if (cellSet == NULL)
{
throw vtkm::cont::ErrorControlBadValue("Bad cast of dynamic cell set.");
}
return container->Item;
return *cellSet;
}
/// Changes the cell set types to try casting to when resolving this dynamic
@ -217,16 +251,6 @@ private:
CellSetContainer;
friend struct detail::DynamicCellSetCopyHelper;
template<typename CellSetType>
VTKM_CONT_EXPORT
vtkm::cont::internal::SimplePolymorphicContainer<CellSetType> *
TryCast() const {
return
dynamic_cast<
vtkm::cont::internal::SimplePolymorphicContainer<CellSetType> *>(
this->CellSetContainer.get());
}
};
namespace detail {
@ -234,22 +258,23 @@ namespace detail {
template<typename Functor>
struct DynamicCellSetTryCellSet
{
const vtkm::cont::CellSet *AbstractCellSet;
vtkm::cont::internal::SimplePolymorphicContainerBase *CellSetContainer;
const Functor &Function;
bool FoundCast;
VTKM_CONT_EXPORT
DynamicCellSetTryCellSet(const vtkm::cont::CellSet &cellSet,
const Functor &f)
: AbstractCellSet(&cellSet), Function(f), FoundCast(false) { }
DynamicCellSetTryCellSet(
vtkm::cont::internal::SimplePolymorphicContainerBase *cellSetContainer,
const Functor &f)
: CellSetContainer(cellSetContainer), Function(f), FoundCast(false) { }
template<typename CellSetType>
VTKM_CONT_EXPORT
void operator()(CellSetType) {
if (!this->FoundCast)
{
const CellSetType *cellSet =
dynamic_cast<const CellSetType *>(this->AbstractCellSet);
CellSetType *cellSet =
detail::DynamicCellSetTryCast<CellSetType>(this->CellSetContainer);
if (cellSet != NULL)
{
this->Function(*cellSet);
@ -259,22 +284,6 @@ struct DynamicCellSetTryCellSet
}
};
template<typename Functor, typename CellSetTypeList>
VTKM_CONT_EXPORT
void CastAndCallCellSet(
const Functor &f,
const vtkm::cont::DynamicCellSetBase<CellSetTypeList> &cellSet)
{
typedef detail::DynamicCellSetTryCellSet<Functor> TryCellSetType;
TryCellSetType tryCellSet = TryCellSetType(cellSet.GetCellSet(), f);
vtkm::ListForEach(tryCellSet, CellSetTypeList());
if (!tryCellSet.FoundCast)
{
throw vtkm::cont::ErrorControlBadValue(
"Could not find appropriate cast for cell set.");
}
}
} // namespace detail
template<typename CellSetList>
@ -282,7 +291,14 @@ template<typename Functor>
VTKM_CONT_EXPORT
void DynamicCellSetBase<CellSetList>::CastAndCall(const Functor &f) const
{
detail::CastAndCallCellSet(f, *this);
typedef detail::DynamicCellSetTryCellSet<Functor> TryCellSetType;
TryCellSetType tryCellSet = TryCellSetType(this->CellSetContainer.get(), f);
vtkm::ListForEach(tryCellSet, CellSetList());
if (!tryCellSet.FoundCast)
{
throw vtkm::cont::ErrorControlBadValue(
"Could not find appropriate cast for cell set.");
}
}
typedef DynamicCellSetBase< VTKM_DEFAULT_CELL_SET_LIST_TAG > DynamicCellSet;