ENH: add const_cast variants for isA<> and refCast<>

- an example of the new, more succinct refConstCast version:

      auto& abc = refConstCast<adjointVectorBoundaryCondition>(Uab);

  older:
      adjointVectorBoundaryCondition& abc =
          refCast<adjointVectorBoundaryCondition>
          (
              const_cast<fvPatchVectorField&>(Uab)
          );
  or:
      adjointVectorBoundaryCondition& abc =
          const_cast<adjointVectorBoundaryCondition&>
          (
              refCast<const adjointVectorBoundaryCondition>(Uab)
          );

- an example of the new, more succinct isA_constCast version:

      auto* acapPtr = isA_constCast<fieldType>(abf[patchi]);

      if (acapPtr)
      {
          auto& acap = *acapPtr;
          ...
      }

  older:
      if (isA<fieldType>(abf[patchi]))
      {
          fieldType& acap =
              const_cast<fieldType&>
              (
                  refCast<const fieldType>(abf[patchi])
              );
          ...
      }

STYLE: remove spurious 'const' qualifier from isA<> use
This commit is contained in:
Mark Olesen
2024-04-12 11:32:55 +02:00
parent 6546dd3f5b
commit 92c329a8a9
6 changed files with 86 additions and 62 deletions

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-2023 OpenCFD Ltd. Copyright (C) 2018-2024 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -24,9 +24,6 @@ License
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Typedef
Foam::typeInfo
Description Description
Basic run-time type information using word as the type's name. Basic run-time type information using word as the type's name.
Used to enhance the standard RTTI to cover I/O. Used to enhance the standard RTTI to cover I/O.
@ -36,18 +33,20 @@ Description
type() type()
\endcode \endcode
The reference type cast template function: The isA functions:
\code
refCast<Type>(r)
\endcode
wraps dynamic_cast to handle failed casts and generate a FatalError.
The isA function:
\code \code
isA<Type>(obj) isA<Type>(obj)
isA_constCast<Type>(obj)
\endcode \endcode
returns const pointer to the cast object, nullptr if cast is not possible which return const or non-const pointers to the cast object,
(can be tested as a bool). nullptr if cast is not possible (can be tested as a bool).
The reference type cast template function:
\code
refCast<Type>(obj)
refConstCast<Type>(obj)
\endcode
wraps dynamic_cast to handle failed casts and generate a FatalError.
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -80,9 +79,9 @@ namespace Foam
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
//- Check if dynamic_cast to \c Type is possible. //- Attempt dynamic_cast to \c Type.
// The template types should \em not include any \c const qualifier. // \note The template types should \em not include any \c const qualifier.
// \returns const pointer to cast object, nullptr if cast is not possible // \return const pointer to cast object, nullptr if cast is not possible
template<class Type, class U> template<class Type, class U>
inline const Type* isA(const U& obj) inline const Type* isA(const U& obj)
{ {
@ -91,6 +90,17 @@ inline const Type* isA(const U& obj)
} }
//- Attempt dynamic_cast to \c Type followed by a const_cast of the result.
// \note The template types should \em not include any \c const qualifier.
// \return non-const pointer to cast object, nullptr if cast is not possible
template<class Type, class U>
inline Type* isA_constCast(const U& obj)
{
const U* p = &obj;
return const_cast<Type*>(dynamic_cast<const Type*>(p));
}
//- Check if typeid of the object and \c Type are identical //- Check if typeid of the object and \c Type are identical
template<class Type, class U> template<class Type, class U>
inline bool isType(const U& obj) inline bool isType(const U& obj)
@ -139,10 +149,10 @@ inline Type& dynamicCast(U& obj, const dictionary& dict)
} }
//- A dynamic_cast (for references). //- A dynamic_cast (for references) to \c Type reference.
//- Generates a FatalError on failed casts and uses the virtual type() // \note Respects the constness of the template types.
//- method for error messages. // \return reference to cast object, or FatalError on failed casts
// Respects the constness of the template types. // and use the virtual type() method for error messages.
template<class Type, class U> template<class Type, class U>
inline Type& refCast(U& obj) inline Type& refCast(U& obj)
{ {
@ -161,6 +171,29 @@ inline Type& refCast(U& obj)
} }
//- A dynamic_cast (for const references) to \c Type reference,
//- followed by a const_cast of the result.
// \note The template types should \em not include any \c const qualifier.
// \return non-const reference to cast object, or FatalError on failed casts
// and use the virtual type() method for error messages.
template<class Type, class U>
inline Type& refConstCast(const U& obj)
{
const U* p = &obj;
const Type* casted = dynamic_cast<const Type*>(p);
if (!casted)
{
FatalErrorInFunction
<< "Attempt to cast type " << obj.type()
<< " to type " << Type::typeName
<< abort(FatalError);
}
return const_cast<Type&>(*casted);
}
//- A dynamic_cast (for references) that generates FatalIOError on failed casts, //- A dynamic_cast (for references) that generates FatalIOError on failed casts,
//- uses the virtual type() method for error messages. //- uses the virtual type() method for error messages.
// Respects the constness of the template types. // Respects the constness of the template types.
@ -205,6 +238,8 @@ inline Type& refCast(U& obj, const label index)
} }
// * * * * * * * * * * * * * * * * Functors * * * * * * * * * * * * * * * * //
//- Test if dynamic_cast to Type is possible, as a functor //- Test if dynamic_cast to Type is possible, as a functor
template<class Type> template<class Type>
struct isAOp struct isAOp

View File

@ -51,19 +51,15 @@ namespace functionObjects
void Foam::functionObjects::writeFreeSurface::writeData() void Foam::functionObjects::writeFreeSurface::writeData()
{ {
// refCast<interfaceTrackingFvMesh> // refCast<interfaceTrackingFvMesh>
auto* itm = auto* itm = isA_constCast<interfaceTrackingFvMesh>(mesh_);
const_cast<interfaceTrackingFvMesh*>
(
isA<interfaceTrackingFvMesh>(mesh_)
);
if (!itm) if (itm)
{ {
// FatalError itm->writeVTKControlPoints();
} }
else else
{ {
itm->writeVTKControlPoints(); // FatalError
} }
} }

View File

@ -139,22 +139,22 @@ void Foam::freeSurfacePressureFvPatchScalarField::updateCoeffs()
// refCast<interfaceTrackingFvMesh> // refCast<interfaceTrackingFvMesh>
auto* itm = auto* itm =
const_cast<interfaceTrackingFvMesh*> isA_constCast<interfaceTrackingFvMesh>
( (
isA<interfaceTrackingFvMesh>(patch().boundaryMesh().mesh()) patch().boundaryMesh().mesh()
); );
if (!itm) if (itm)
{
// FatalError
}
else
{ {
operator== operator==
( (
pa_ + itm->freeSurfacePressureJump() pa_ + itm->freeSurfacePressureJump()
); );
} }
else
{
// FatalError
}
fixedValueFvPatchScalarField::updateCoeffs(); fixedValueFvPatchScalarField::updateCoeffs();
} }

View File

@ -189,7 +189,7 @@ void Foam::distributedDILUPreconditioner::receive
for (const label inti : selectedInterfaces) for (const label inti : selectedInterfaces)
{ {
const auto& intf = interfaces[inti].interface(); const auto& intf = interfaces[inti].interface();
const auto* ppp = isA<const processorLduInterface>(intf); const auto* ppp = isA<processorLduInterface>(intf);
auto& recvBuf = recvBufs_[inti]; auto& recvBuf = recvBufs_[inti];
recvBuf.resize_nocopy(interfaceBouCoeffs[inti].size()); recvBuf.resize_nocopy(interfaceBouCoeffs[inti].size());
@ -221,7 +221,7 @@ void Foam::distributedDILUPreconditioner::send
for (const label inti : selectedInterfaces) for (const label inti : selectedInterfaces)
{ {
const auto& intf = interfaces[inti].interface(); const auto& intf = interfaces[inti].interface();
const auto* ppp = isA<const processorLduInterface>(intf); const auto* ppp = isA<processorLduInterface>(intf);
const auto& faceCells = intf.faceCells(); const auto& faceCells = intf.faceCells();
auto& sendBuf = sendBufs_[inti]; auto& sendBuf = sendBufs_[inti];
@ -581,7 +581,7 @@ Foam::distributedDILUPreconditioner::distributedDILUPreconditioner
if (interfaces.set(inti)) if (interfaces.set(inti))
{ {
const auto& intf = interfaces[inti].interface(); const auto& intf = interfaces[inti].interface();
const auto* ppp = isA<const processorLduInterface>(intf); const auto* ppp = isA<processorLduInterface>(intf);
if (ppp) if (ppp)
{ {
const label nbrColour = procColours[ppp->neighbProcNo()]; const label nbrColour = procColours[ppp->neighbProcNo()];
@ -603,11 +603,11 @@ Foam::distributedDILUPreconditioner::distributedDILUPreconditioner
<< endl; << endl;
} }
} }
else //if (isA<const cyclicAMILduInterface>(intf)) else //if (isA<cyclicAMILduInterface>(intf))
{ {
haveGlobalCoupled = true; haveGlobalCoupled = true;
const auto* AMIpp = isA<const cyclicAMILduInterface>(intf); const auto* AMIpp = isA<cyclicAMILduInterface>(intf);
if (AMIpp) if (AMIpp)
{ {
//const auto& AMI = //const auto& AMI =
@ -681,12 +681,12 @@ Foam::distributedDILUPreconditioner::distributedDILUPreconditioner
const auto& intf = interfaces[inti].interface(); const auto& intf = interfaces[inti].interface();
label nbrInti = -1; label nbrInti = -1;
const auto* AMIpp = isA<const cyclicAMILduInterface>(intf); const auto* AMIpp = isA<cyclicAMILduInterface>(intf);
if (AMIpp) if (AMIpp)
{ {
nbrInti = AMIpp->neighbPatchID(); nbrInti = AMIpp->neighbPatchID();
} }
const auto* cycpp = isA<const cyclicLduInterface>(intf); const auto* cycpp = isA<cyclicLduInterface>(intf);
if (cycpp) if (cycpp)
{ {
nbrInti = cycpp->neighbPatchID(); nbrInti = cycpp->neighbPatchID();

View File

@ -279,7 +279,7 @@ Foam::label Foam::processorColour::cellColour
if if
( (
patches.set(inti) patches.set(inti)
&& !isA<const processorLduInterface>(patches[inti]) && !isA<processorLduInterface>(patches[inti])
) )
{ {
// 'global' interface. Seed faceCells with patch index // 'global' interface. Seed faceCells with patch index

View File

@ -160,34 +160,27 @@ Foam::label Foam::cuttingPlane::calcCellCuts
} }
if (debug && isA<fvMesh>(mesh)) const fvMesh* fvMeshPtr = nullptr;
if (debug && (fvMeshPtr = isA<fvMesh>(mesh)) != nullptr)
{ {
const auto& fvmesh = dynamicCast<const fvMesh>(mesh); auto tcellCutsDebug = volScalarField::New
volScalarField cCuts
(
IOobject
( (
"cuttingPlane.cellCuts", "cuttingPlane.cellCuts",
fvmesh.time().timeName(), IOobjectOption::NO_REGISTER,
fvmesh.time(), *fvMeshPtr,
IOobject::NO_READ, dimensionedScalar(dimless, Foam::zero{})
IOobject::NO_WRITE,
IOobject::NO_REGISTER
),
fvmesh,
dimensionedScalar(dimless, Zero)
); );
auto& cellCutsDebug = tcellCutsDebug.ref();
auto& cCutsFld = cCuts.primitiveFieldRef(); auto& fld = cellCutsDebug.primitiveFieldRef();
for (const label celli : cellCuts) for (const label celli : cellCuts)
{ {
cCutsFld[celli] = 1; fld[celli] = 1;
} }
Pout<< "Writing cut types:" << cCuts.objectPath() << endl; Pout<< "Writing cut types:" << cellCutsDebug.objectPath() << endl;
cCuts.write(); cellCutsDebug.write();
} }