ENH: use pointer checks for dynamicCast, refCast

- avoids try/catch exception handling

STYLE: prefer refCast (shorter) to dynamicCast where possible
This commit is contained in:
Mark Olesen
2022-09-15 10:20:57 +02:00
parent 512f558549
commit b9ca63b118
11 changed files with 120 additions and 132 deletions

View File

@ -65,7 +65,7 @@ label writeDimFields
{
typedef VolumeInternalField<Type> FieldType;
const fvMesh& mesh = dynamicCast<const fvMesh>(ensMesh.mesh());
const auto& mesh = refCast<const fvMesh>(ensMesh.mesh());
label count = 0;

View File

@ -88,7 +88,7 @@ label writeVolFields
{
typedef VolumeField<Type> FieldType;
const fvMesh& mesh = dynamicCast<const fvMesh>(ensMesh.mesh());
const auto& mesh = refCast<const fvMesh>(ensMesh.mesh());
label count = 0;

View File

@ -165,7 +165,7 @@ if (argList::postProcess(argc, argv))
// Report to output (avoid overwriting values from simulation)
profiling::print(Info);
}
catch (const IOerror& err)
catch (const Foam::IOerror& err)
{
Warning<< err << endl;
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2019 OpenCFD Ltd.
Copyright (C) 2018-2022 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -38,18 +38,16 @@ Description
The reference type cast template function:
\code
refCast<T>(r)
refCast<Type>(r)
\endcode
wraps dynamic_cast to handle the bad_cast exception and generate a
FatalError.
wraps dynamic_cast to handle failed casts and generate a FatalError.
The isA function:
\code
isA<T>(r)
isA<Type>(obj)
\endcode
returns true if r is of type T or derived from type T.
returns const pointer to the cast object, nullptr if cast is not possible
(can be tested as a bool).
\*---------------------------------------------------------------------------*/
@ -82,153 +80,144 @@ namespace Foam
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
//- Reference type cast template function,
//- wraps dynamic_cast to handle bad_cast exception and generate a FatalError.
template<class To, class From>
inline To& dynamicCast(From& r)
//- Check if dynamic_cast to \c Type is possible
// \returns const pointer to cast object, nullptr if cast is not possible
template<class Type, class U>
inline const Type* isA(const U& obj)
{
try
{
return dynamic_cast<To&>(r);
}
catch (const std::bad_cast&)
{
FatalErrorInFunction
<< "Attempt to cast type " << typeid(r).name()
<< " to type " << typeid(To).name()
<< abort(FatalError);
return dynamic_cast<To&>(r);
}
const U* p = &obj;
return dynamic_cast<const Type*>(p);
}
//- Reference type cast template function,
//- wraps dynamic_cast to handle bad_cast exception and generate a FatalError.
template<class To, class From>
inline To& dynamicCast(From& r, const dictionary& d)
//- Check if typeid of the object and \c Type are identical
template<class Type, class U>
inline bool isType(const U& obj)
{
try
return typeid(Type) == typeid(obj);
}
//- A dynamic_cast (for references) that generates FatalError on failed casts
template<class Type, class U>
inline Type& dynamicCast(U& obj)
{
U* p = &obj;
Type* casted = dynamic_cast<Type*>(p);
if (!casted)
{
return dynamic_cast<To&>(r);
FatalErrorInFunction
<< "Attempt to cast type " << typeid(U).name()
<< " to type " << typeid(Type).name()
<< abort(FatalError);
}
catch (const std::bad_cast&)
return *casted;
}
//- A dynamic_cast (for references) that generates FatalIOError on failed casts
template<class Type, class U>
inline Type& dynamicCast(U& obj, const dictionary& dict)
{
U* p = &obj;
Type* casted = dynamic_cast<Type*>(p);
if (!casted)
{
FatalIOErrorInFunction(d)
<< "Attempt to cast type " << typeid(r).name()
<< " to type " << typeid(To).name()
FatalIOErrorInFunction(dict)
<< "Attempt to cast type " << typeid(U).name()
<< " to type " << typeid(Type).name()
<< abort(FatalIOError);
return dynamic_cast<To&>(r);
}
return *casted;
}
//- Reference type cast template function.
// As per dynamicCast, but handles type names for the error messages
// via the virtual type() method.
template<class To, class From>
inline To& refCast(From& r)
//- A dynamic_cast (for references) that generates FatalError on failed casts,
//- uses the virtual type() method for error messages.
template<class Type, class U>
inline Type& refCast(U& obj)
{
try
{
return dynamic_cast<To&>(r);
}
catch (const std::bad_cast&)
U* p = &obj;
Type* casted = dynamic_cast<Type*>(p);
if (!casted)
{
FatalErrorInFunction
<< "Attempt to cast type " << r.type()
<< " to type " << To::typeName
<< "Attempt to cast type " << obj.type()
<< " to type " << Type::typeName
<< abort(FatalError);
return dynamic_cast<To&>(r);
}
return *casted;
}
//- Reference type cast template function.
// As per dynamicCast, but handles type names for the error messages
// via the virtual type() method.
// Can use index to convey the context.
template<class To, class From>
inline To& refCast(From& r, const label index)
//- A dynamic_cast (for references) that generates FatalIOError on failed casts,
//- uses the virtual type() method for error messages.
template<class Type, class U>
inline Type& refCast(U& obj, const dictionary& dict)
{
try
U* p = &obj;
Type* casted = dynamic_cast<Type*>(p);
if (!casted)
{
return dynamic_cast<To&>(r);
FatalIOErrorInFunction(dict)
<< "Attempt to cast type " << obj.type()
<< " to type " << Type::typeName
<< abort(FatalIOError);
}
catch (const std::bad_cast&)
return *casted;
}
//- A dynamic_cast (for references) that generates FatalError on failed casts,
//- uses the virtual type() method for error messages.
//- The index can be used to convey additional context.
template<class Type, class U>
inline Type& refCast(U& obj, const label index)
{
U* p = &obj;
Type* casted = dynamic_cast<Type*>(p);
if (!casted)
{
FatalErrorInFunction
<< "Attempt to cast type " << r.type()
<< " to type " << To::typeName
<< "Attempt to cast type " << obj.type()
<< " to type " << Type::typeName
<< " at index " << index
<< abort(FatalError);
return dynamic_cast<To&>(r);
}
return *casted;
}
//- Reference type cast template function.
// As per dynamicCast, but handles type names for the error messages
// via the virtual type() method.
template<class To, class From>
inline To& refCast(From& r, const dictionary& d)
{
try
{
return dynamic_cast<To&>(r);
}
catch (const std::bad_cast&)
{
FatalIOErrorInFunction(d)
<< "Attempt to cast type " << r.type()
<< " to type " << To::typeName
<< abort(FatalIOError);
return dynamic_cast<To&>(r);
}
}
//- Check if dynamic_cast to TargetType is possible
template<class TargetType, class Type>
inline const TargetType* isA(const Type& t)
{
const Type* p = &t;
return dynamic_cast<const TargetType*>(p);
}
//- Check if dynamic_cast to TargetType is possible, as a functor
template<class TargetType>
//- Test if dynamic_cast to Type is possible, as a functor
template<class Type>
struct isAOp
{
template<class Type>
inline bool operator()(const Type& t) const
template<class U>
bool operator()(const U& obj) const
{
return isA<TargetType,Type>(t);
return isA<Type, U>(obj);
}
};
//- Check is typeid is identical to the TargetType
template<class TargetType, class Type>
inline bool isType(const Type& t)
{
return typeid(TargetType) == typeid(t);
}
//- Check is typeid is identical to the TargetType, as a functor
template<class TargetType>
//- Test if typeid is identical to the Type, as a functor
template<class Type>
struct isTypeOp
{
template<class Type>
inline bool operator()(const Type& t) const
template<class U>
bool operator()(const U& obj) const
{
return isType<TargetType,Type>(t);
return isType<Type, U>(obj);
}
};

View File

@ -246,8 +246,7 @@ static inline std::string entryToString
else
{
// Fail for non-primitiveEntry
const primitiveEntry& pe =
dynamicCast<const primitiveEntry>(*eptr);
const auto& pe = dynamicCast<const primitiveEntry>(*eptr);
if (pe.size() == 1 && pe[0].isStringType())
{

View File

@ -576,7 +576,7 @@ bool Foam::expressions::fvExprDriver::updateSet
const label oldSize = setPtr->size();
bool updated = false;
const auto& mesh = dynamicCast<const polyMesh>(setPtr->db());
const auto& mesh = refCast<const polyMesh>(setPtr->db());
if (debug)
{

View File

@ -47,7 +47,7 @@ Foam::exprValuePointPatchField<Type>::exprValuePointPatchField
(
fvPatch::lookupPatch
(
dynamicCast<const facePointPatch>(this->patch()).patch()
refCast<const facePointPatch>(this->patch()).patch()
)
)
{}
@ -69,7 +69,7 @@ Foam::exprValuePointPatchField<Type>::exprValuePointPatchField
(
fvPatch::lookupPatch
(
dynamicCast<const facePointPatch>(this->patch()).patch()
refCast<const facePointPatch>(this->patch()).patch()
),
rhs.driver_,
dict_
@ -110,7 +110,7 @@ Foam::exprValuePointPatchField<Type>::exprValuePointPatchField
(
fvPatch::lookupPatch
(
dynamicCast<const facePointPatch>(this->patch()).patch()
refCast<const facePointPatch>(this->patch()).patch()
),
dict_
)
@ -164,7 +164,7 @@ Foam::exprValuePointPatchField<Type>::exprValuePointPatchField
(
fvPatch::lookupPatch
(
dynamicCast<const facePointPatch>(this->patch()).patch()
refCast<const facePointPatch>(this->patch()).patch()
),
rhs.driver_,
dict_
@ -185,7 +185,7 @@ Foam::exprValuePointPatchField<Type>::exprValuePointPatchField
(
fvPatch::lookupPatch
(
dynamicCast<const facePointPatch>(this->patch()).patch()
refCast<const facePointPatch>(this->patch()).patch()
),
rhs.driver_,
dict_

View File

@ -411,7 +411,7 @@ combineSurfaceGeometry
{
if (stObject == regionType_)
{
const polySurface& s = dynamicCast<const polySurface>(obr());
const auto& s = refCast<const polySurface>(obr());
if (Pstream::parRun())
{
@ -471,7 +471,7 @@ Foam::functionObjects::fieldValues::surfaceFieldValue::totalArea() const
if (stObject == regionType_)
{
const polySurface& s = dynamicCast<const polySurface>(obr());
const auto& s = refCast<const polySurface>(obr());
totalArea = gSum(s.magSf());
}
@ -536,7 +536,7 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::update()
}
case stObject:
{
const polySurface& s = dynamicCast<const polySurface>(obr());
const auto& s = refCast<const polySurface>(obr());
nFaces_ = returnReduce(s.size(), sumOp<label>());
break;
}
@ -1206,7 +1206,7 @@ bool Foam::functionObjects::fieldValues::surfaceFieldValue::write()
{
if (stObject == regionType_)
{
const polySurface& s = dynamicCast<const polySurface>(obr());
const auto& s = refCast<const polySurface>(obr());
Sf = s.Sf();
}
else if (sampledPtr_)

View File

@ -848,7 +848,7 @@ Foam::List<Foam::scalar> Foam::lumpedPointMovement::areas
// fvMesh and has pressure field
if (isA<fvMesh>(pmesh))
{
const fvMesh& mesh = dynamicCast<const fvMesh>(pmesh);
const auto& mesh = refCast<const fvMesh>(pmesh);
// Face areas (on patches)
const surfaceVectorField::Boundary& patchSf =
@ -931,7 +931,7 @@ bool Foam::lumpedPointMovement::forcesAndMoments
// fvMesh and has pressure field
if (isA<fvMesh>(pmesh) && pPtr)
{
const fvMesh& mesh = dynamicCast<const fvMesh>(pmesh);
const auto& mesh = refCast<const fvMesh>(pmesh);
const volScalarField& p = *pPtr;
// Face centres (on patches)

View File

@ -1191,7 +1191,7 @@ Foam::isoSurfaceCell::isoSurfaceCell
if (debug && isA<fvMesh>(mesh))
{
const auto& fvmesh = dynamicCast<const fvMesh>(mesh);
const auto& fvmesh = refCast<const fvMesh>(mesh);
volScalarField debugField
(

View File

@ -967,7 +967,7 @@ Foam::isoSurfaceTopo::isoSurfaceTopo
if (debug && isA<fvMesh>(mesh))
{
const auto& fvmesh = dynamicCast<const fvMesh>(mesh);
const auto& fvmesh = refCast<const fvMesh>(mesh);
volScalarField debugField
(