Untitled :: Boost.OpenMethod

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.

Edit this Page