C++ Friendship Does Not Pass Through a Yield-Curve Inheritance Chain
Summary
The document describes a C++ access-control problem when a custom OIS curve derives from QuantLib’s piecewise yield curve and uses a custom bootstrapper. The bootstrapper needs access to private or protected members across the derived curve and its base classes, but declaring it as a friend of the derived class does not grant access to the base classes’ members. Friendship is not inherited or transitive, so each class whose private members must be accessed needs to grant that access explicitly, or the design must use another access mechanism.
The author reports that the setup compiles with the default iterative bootstrapper but fails with the custom one, and provides class declarations and an instantiation illustrating the issue. The discussion is focused on C++ templates and QuantLib’s implementation structure; it does not explain yield-curve construction or provide a trading method. The practical lesson is limited to resolving access-control errors when extending this library design.
Key ideas
- Friendship in C++ grants access only to the class that declares the friend.
- Friendship is neither inherited by derived classes nor passed through a class’s base classes.
- A custom bootstrapper that needs private members across a hierarchy may require explicit friendship in each relevant class.
- The example concerns a custom QuantLib OIS curve and bootstrapper, rather than curve pricing methodology.
Tags
Full text
# QuantLib C++: Friendship dilemma between derived class from PiecewiseYieldCurve and Bootstrap class
# QuantLib C++: Friendship dilemma between derived class from PiecewiseYieldCurve and Bootstrap class
I derived a class template, `OISCurve<Traits,Interpolator,Bootstrap>`, from `PiecewiseYieldCurve<Traits,Interpolator,Bootstrap>`. The functionality provided by the class works fine as long as i use the default class `IterativeBootstrap` as the third template parameter.
On the other side I have implemented a bootstrap algorithm as the `calculate()` method of a new class, `OISBootstrap`. The implementation follows the structure of the default class `IterativeBootstrap`.
I have also added in my derived class the following friend class as done in the declaration of `PiecewiseYieldCurve<Traits,Interpolator,Bootstrap>`:
```
friend class Bootstrap <PiecewiseYieldCurve<Traits, Interpolator, Bootstrap>>;
```
`OISBootstrap` needs in fact access to private members of `OISCurve`, but also to private members of `PiecewiseYieldCurve` and to its derived members as well.
Unfortunately I'm still getting compiling errors saying that `OISBootstrap` cannot access private/protected members of the classes `OISCurve` derives from, like `PiecewiseYieldCurve`, `InterpolatedCurve` and `TermStructure`.
Question: The declaration of friendship in `PiecewiseYieldCurve` shouldn't suffice to give access to `OISBootstrap` as well? (of course not since i'm getting compiling erros but i hope i made my point)
Thanks for the help.
## EDIT
OISCurve.h
```
template <class Traits, class Interpolator,
template <class> class Bootstrap = IterativeBootstrap>
class OISCurve : public PiecewiseYieldCurve < Traits, Interpolator, Bootstrap >
{
public:
OISCurve(
Natural settlementDays,
const Calendar& calendar,
const std::vector<boost::shared_ptr<Quote>>& quotes,
const DayCounter& dayCounter,
Real accuracy,
const Interpolator& i = Interpolator(),
const Bootstrap<PiecewiseYieldCurve<Traits, Interpolator, Bootstrap>>& bootstrap = Bootstrap<PiecewiseYieldCurve<Traits, Interpolator, Bootstrap>>());
friend std::vector<boost::shared_ptr<RateHelper>> constructRateHelpers(const std::vector<boost::shared_ptr<Quote>>& quotes);
}
```
OISBootstrap
```
template<class Curve>
class OISBootstrap
{
protected:
typedef typename Curve::traits_type Traits;
typedef typename Curve::interpolator_type Interpolator;
public:
OISBootstrap();
void setup(Curve* ts);
virtual void calculate() const;
virtual ~OISBootstrap();
protected:
void initialize() const;
void setupHelpers() const;
Curve* ts_;
Size n_;
mutable bool initialized_, validCurve_;
mutable Size firstAliveHelper_, alive_;
mutable std::vector<Real> previousData_;
};
```
Instantiation
```
boost::shared_ptr<YieldTermStructure> oisCurve( new
OISCurve<Discount, LogLinear, OISBootstrap>(2, TARGET(), _quotes, Actual360(), 1.0e-12));
```Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.