ffig
ffig copied to clipboard
Generating 'onion-style' edit wrappers
In the following example we wrap a simple interface, called IMarketData, with a 'onion-style' edit class that allows you to change the implementation of any simple getters of the interface. Most of this should be easy to generate from the signatures of the class. Would this be something worth adding to FFIG?
#include <memory>
struct IMarketData : public std::enable_shared_from_this
{
virtual ~IMarketData() = default;
virtual double zero_coupon_rate(int date) const = 0;
virtual double euro_usd_rate(int date) const = 0;
};
//
// FFIG could generate everything below
//
struct CMarketDataEdits
{
std::function<double(const IMarketData&, int)> zero_coupon_rate_f_;
std::function<double(const IMarketData&, int)> euro_usd_rate_f_;
MarketDataEdits& zero_coupon_rate_f(std::function<double(int)> f) &&
{
zero_coupon_rate_f_ = [f](const IMarketData&, int i) { return f(i); };
return *this;
}
MarketDataEdits&
zero_coupon_rate_f(std::function<double(const IMarketData&, int)> f) &&
{
zero_coupon_rate_f_ = f;
return *this;
}
MarketDataEdits& euro_usd_rate_f(std::function<double(int)> f) &&
{
euro_usd_rate_f_ = [f](const IMarketData&, int i) { return f(i); };
return *this;
}
MarketDataEdits&
euro_usd_rate_f(std::function<double(const IMarketData&, int)> f) &&
{
euro_usd_rate_f_ = f;
return *this;
}
};
class CMarketDataWrapper : public IMarketData
{
std::shared_ptr<const IMarketData> underlying_;
std::function<double(const IMarketData&, int)> zero_coupon_rate_f_;
std::function<double(const IMarketData&, int)> euro_usd_rate_f_;
public:
CMarketDataWrapper(const IMarketData& data, const CMarketDataEdits& edits)
: underlying_(data.shared_from_this()),
zero_coupon_rate_f_(edits.zero_coupon_rate_f_),
euro_usd_rate_f_(edits.euro_usd_rate_f_)
{
}
double zero_coupon_rate(int i) const override
{
return zero_coupon_rate_f_ ? zero_coupon_rate_f_(*underlying_, i)
: underlying_->zero_coupon_rate(i);
}
double euro_usd_rate(int i) const override
{
return euro_usd_rate_f_ ? euro_usd_rate_f_(*underlying_, i)
: underlying_->euro_usd_rate(i);
}
};
extern const IMarketData& baseData;
auto e = MarketDataEdits()
.zero_coupon_rate_f([](int i) { return i < 100 ? 0.0 : 0.1; })
.euro_usd_rate_f([](const IMarketData& d, int i) {
return d.euro_usd_rate(i) * 1.1;
});
auto modified_data = MarketDataWrapper(baseData, edits);
This should be possible to handle in the same way that we handle C++ mock generation.