I have the following old code that used to work on "older" combinations/versions of C , QuantLib and Boost.
While was playing around with the idea of upgrading to newer versions ie C 11, QuantLib >= 1.76, boost >= 1_71 building now throws the following "conversion" error(s).
I am using [options] g -std=gnu 11
hestonslvmodule.cpp:456:7: warning: narrowing conversion of ‘(QuantLib::FdmHestonGreensFct::Algorithm)greensAlgorithm’ from ‘Quant
Lib::FdmHestonGreensFct::Algorithm’ to ‘QuantLib::Real’ {aka ‘double’} [-Wnarrowing]
456 | greensAlgorithm,
| ^~~~~~~~~~~~~~~
hestonslvmodule.cpp:457:7: error: cannot convert ‘const QuantLib::FdmSquareRootFwdOp::TransformationType’ to ‘const QuantLib::FdmH
estonGreensFct::Algorithm’ in initialization
457 | transformationType,
| ^~~~~~~~~~~~~~~~~~
| |
| const QuantLib::FdmSquareRootFwdOp::TransformationType
hestonslvmodule.cpp:458:7: error: cannot convert ‘const QuantLib::FdmSchemeDesc’ to ‘const QuantLib::FdmSquareRootFwdOp::Transform
ationType’ in initialization
458 | schemeDesc
| ^~~~~~~~~~
| |
| const QuantLib::FdmSchemeDesc
hestonslvmodule.cpp:459:5: error: could not convert ‘<brace-enclosed initializer list>()’ from ‘<brace-enclosed initializer list>’
to ‘const QuantLib::FdmSchemeDesc’
459 | };
| ^
| |
| <brace-enclosed initializer list>
I did pick up some comments on brace lists and having to have the "right" C version to be able to cope with these but my C is not good enough to pick up on what exactly the problem could be in (this is my opinion/best guess) of which part of the code is acting "funny" now, causing the problems.
FdmSchemeDesc getFdmSchemeDesc(const std::string& schemeDescStr) {
return (schemeDescStr == "ModifiedCraigSneyd") ? FdmSchemeDesc::ModifiedCraigSneyd()
: (schemeDescStr == "CraigSneyd") ? FdmSchemeDesc::CraigSneyd()
: (schemeDescStr == "Hundsdorfer") ? FdmSchemeDesc::Hundsdorfer()
: (schemeDescStr == "ModifiedHundsdorfer") ? FdmSchemeDesc::ModifiedHundsdorfer()
: (schemeDescStr == "ImplicitEuler") ? FdmSchemeDesc::ImplicitEuler()
: (schemeDescStr == "ExplicitEuler") ? FdmSchemeDesc::ExplicitEuler()
: (schemeDescStr == "Douglas") ? FdmSchemeDesc::Douglas()
: (stop("unknown scheme type"), FdmSchemeDesc::ExplicitEuler());
}
ending up being used here ...
class HestonSLVFDMModel {
public:
HestonSLVFDMModel(QuantLib::Date referenceDate,
QuantLib::Date maxDate,
Function localVol,
S4 hestonProcess,
S4 fdmParams) {
if (!fdmParams.is("HestonSLVFDMParams"))
stop("Last parameter needs to be of type HestonSLVFDMParams");
const std::string greensAlgoStr
= as<std::string>(fdmParams.slot("greensAlgorithm"));
const FdmHestonGreensFct::Algorithm greensAlgorithm =
(greensAlgoStr == "Gaussian") ? FdmHestonGreensFct::Gaussian
: (greensAlgoStr == "ZeroCorrelation") ? FdmHestonGreensFct::ZeroCorrelation
: (greensAlgoStr == "SemiAnalytical") ? FdmHestonGreensFct::SemiAnalytical
: (stop("unknown Greens function type"), FdmHestonGreensFct::SemiAnalytical);
const std::string trafoTypeStr
= as<std::string>(fdmParams.slot("transformationType"));
const FdmSquareRootFwdOp::TransformationType transformationType =
(trafoTypeStr == "Plain") ? FdmSquareRootFwdOp::Plain
: (trafoTypeStr == "Power") ? FdmSquareRootFwdOp::Power
: (trafoTypeStr == "Log") ? FdmSquareRootFwdOp::Log
: (stop("unknown transformation type"), FdmSquareRootFwdOp::Log);
const std::string schemeDescStr
= as<std::string>(fdmParams.slot("fdmSchemeType"));
const FdmSchemeDesc schemeDesc = getFdmSchemeDesc(schemeDescStr);
const HestonSLVFokkerPlanckFdmParams params = {
as<unsigned>(fdmParams.slot("xGrid")),
as<unsigned>(fdmParams.slot("vGrid")),
as<unsigned>(fdmParams.slot("tMaxStepsPerYear")),
as<unsigned>(fdmParams.slot("tMinStepsPerYear")),
as<Real>(fdmParams.slot("tStepNumberDecay")),
as<unsigned>(fdmParams.slot("predictionCorrectionSteps")),
as<Real>(fdmParams.slot("x0Density")),
as<Real>(fdmParams.slot("localVolEpsProb")),
as<unsigned>(fdmParams.slot("maxIntegrationIterations")),
as<Real>(fdmParams.slot("vLowerEps")),
as<Real>(fdmParams.slot("vUpperEps")),
as<Real>(fdmParams.slot("vMin")),
as<Real>(fdmParams.slot("v0Density")),
as<Real>(fdmParams.slot("vLowerBoundDensity")),
as<Real>(fdmParams.slot("vUpperBoundDensity")),
as<Real>(fdmParams.slot("leverageFctPropEps")),
greensAlgorithm,
transformationType,
schemeDesc
}; // THIS IS LINE 459
...
So my question would be - is there an elegant or quick way of fixing the code with respect to handling these <brace-enclosed initializer list>()
"conversions"?
Like I said these are all "greek to me" so I would appreciate any hints of how to apply quick fixes to such (think I saw somewhere just additional set of {}
curly braces being added)? And also feel free to correct me if I am on the wrong path regarding the error source here?
Thanks
CodePudding user response:
The errors are narrowing conversions, which are never allowed in uniform initializers.
That's relevant because aggregate initialization existed all along and did not have that restriction. Now in C 11 world, aggregate initialization is just a form of uniform initialization, with ditto narrowing rules.
You should explicitly convert the respective values (checking that the conversion is safe!)
E.g.
struct X { short i; };
int init = 42;
X x{init}; // not ok
Explicitly converting makes it ok:
X x{static_cast<short>(init)}; // ok