mirror of
https://github.com/boostorg/openmethod.git
synced 2026-01-27 19:12:11 +00:00
77 lines
2.5 KiB
Plaintext
77 lines
2.5 KiB
Plaintext
|
|
## Alternatives to virtual_ptr
|
|
|
|
Virtual arguments can be passed as plain references. In a method declaration,
|
|
parameters with a type decorated with `virtual_` are considered in overrider
|
|
selection (along with `virtual_ptr` parameters).
|
|
|
|
For example, the `poke` open-method in the Animals example can be rewritten as:
|
|
|
|
[source,c++]
|
|
----
|
|
include::{examplesdir}/virtual_.cpp[tag=virtual_parameter,indent=0]
|
|
|
|
int main() {
|
|
boost::openmethod::initialize();
|
|
|
|
Cat cat;
|
|
poke(std::cout, cat); // hiss
|
|
}
|
|
----
|
|
|
|
Note that `virtual_` is not used in the overrider. It is also removed from the
|
|
method's signature.
|
|
|
|
By itself, `virtual_` does not provide any benefits. Passing the virtual
|
|
argument by reference almost compiles to the same code as creating a
|
|
`virtual_ptr`, using it for one call, then throwing it way. The only difference
|
|
is that the virtual argument is passed as one pointer instead of two.
|
|
|
|
However, we can now customize how the vptr is obtained. When the method sees a
|
|
`virtual_` parameter, it looks for a `boost_openmethod_vptr` function that takes
|
|
the parameter (by const reference), and returns a `vptr_type`. If one is found,
|
|
it is called to obtain the vptr. The vptr for a specific registered class can be
|
|
obtained via a variable template `static_vptr`, nested in class `default_policy`
|
|
(more on policies below).
|
|
|
|
In the following example, we embed a vptr in the object, just like the vptr for
|
|
native virtual functions:
|
|
|
|
[source,c++]
|
|
----
|
|
include::{examplesdir}/virtual_.cpp[tag=virtual_intrusive,indent=0]
|
|
|
|
int main() {
|
|
boost::openmethod::initialize();
|
|
|
|
Cat cat;
|
|
poke(std::cout, cat); // hiss
|
|
}
|
|
----
|
|
|
|
NOTE: With this approach, classes need not be polymorphic. A virtual
|
|
destructor might be needed for correct destruction of objects, but it is not
|
|
required by the library.
|
|
|
|
The `with_vptr` CRTP class automates the creation and management of embedded
|
|
vptrs.
|
|
|
|
[source,c++]
|
|
----
|
|
include::{examplesdir}/virtual_.cpp[tag=with_vptr,indent=0]
|
|
|
|
int main() {
|
|
boost::openmethod::initialize();
|
|
|
|
Cat cat;
|
|
poke(std::cout, cat); // hiss
|
|
}
|
|
----
|
|
|
|
If `with_vptr` is passed only the class being defined, it adds a vptr to it, and
|
|
defines a `boost_openmethod_vptr` friend function. If more classes are passed,
|
|
they must be the direct bases of the class potentially involved in open-method
|
|
calls. Its constructor and destructor set the vptr to point to the v-table for
|
|
the class. `with_vptr` also takes care of registering the classes, so this time
|
|
the call to `BOOST_OPENMETHOD_CLASSES` is not needed.
|