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; typedef VolumeInternalField<Type> FieldType;
const fvMesh& mesh = dynamicCast<const fvMesh>(ensMesh.mesh()); const auto& mesh = refCast<const fvMesh>(ensMesh.mesh());
label count = 0; label count = 0;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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