- Note
-
This section uses overrider containers, described in the Headers section.
friend is a controversial feature. OpenMethod aims to interact well with all
of C++, as much as feasible for a library, and leaves the choice of using
friend, or not, to the user.
Let’s consider yet another variation of the pay example. This time, we want to
update a balance variable in a Payroll class, when an employee is paid. Thus
we pass the payroll object to the pay method:
BOOST_OPENMETHOD(
pay, (Payroll & payroll, boost::openmethod::virtual_ptr<const Employee>),
double);
BOOST_OPENMETHOD declares an overrider container for pay in the current
namespace, even though it does not define any overrider by itself. We can thus
name the individual address containers in friend declarations. But note that
at this point, the containers have not been specialized yet! In particular, the
fn member function does not exist yet. Instead, we declare friendship to the
container itself:
class Payroll {
public:
double balance() const {
return balance_;
}
private:
double balance_ = 1'000'000.0;
void update_balance(double amount) {
// throw if balance would become negative
balance_ += amount;
}
friend BOOST_OPENMETHOD_OVERRIDER(
pay, (Payroll & payroll, boost::openmethod::virtual_ptr<const Employee>),
double);
friend BOOST_OPENMETHOD_OVERRIDER(
pay,
(Payroll & payroll, boost::openmethod::virtual_ptr<const Salesman>),
double);
};
We can now implement the pay overriders:
BOOST_OPENMETHOD_OVERRIDE(
pay, (Payroll & payroll, boost::openmethod::virtual_ptr<const Employee>),
double) {
double pay = 5000.0;
payroll.update_balance(-pay);
return pay;
}
BOOST_OPENMETHOD_OVERRIDE(
pay,
(Payroll & payroll, boost::openmethod::virtual_ptr<const Salesman> emp),
double) {
double base = next(payroll, emp);
double commission = emp->sales * 0.05;
payroll.update_balance(-commission);
return base + commission;
}
// ...and let's not forget to register the classes
BOOST_OPENMETHOD_CLASSES(Employee, Salesman)
We can also declare friendship en masse:
class Payroll {
public:
double balance() const {
return balance_;
}
private:
double balance_ = 1'000'000.0;
void update_balance(double amount) {
// throw if balance would become negative
balance_ += amount;
}
template<typename...>
friend struct BOOST_OPENMETHOD_OVERRIDERS(pay);
};
Note, however, that this makes all the overriders of any pay method, with
any signature, in the current namespace, friends of Payroll. Unfortunately,
C++ does not currently allow partial specialization of friend declarations.