Registries and Policies
Methods are scoped in a registry. A method can only reference classes in the same registry. If a class is used as a virtual parameter in methods using different registries, it must be registered with each of them.
Class templates use_classes, method, virtual_ptr, and macros
BOOST_OPENMETHOD and
BOOST_OPENMETHOD_CLASSES, take an additional
argument, a registry class, which defaults to default_registry. The
default registry can be overriden by defining the macroprocessor symbol
BOOST_OPENMETHOD_DEFAULT_REGISTRY
before including <boost/openmethod/core.hpp>. The value of the symbol is
used as a default template parameter for use_classes, method, virtual_ptr,
and others. Once the core header has been included, changing
BOOST_OPENMETHOD_DEFAULT_REGISTRY has no effect.
A registry has a collection of policies. Each policy belongs to a policy
category. A registry may contain at most one policy of each category. Policies
control how type information is obtained, how vptrs are acquired, how errors are
handled and reported, etc. While the behavior of initialize can be
customized via options, policies are primarily involved in in method dispatch.
Policies are placed in the boost::openmethod::policies namespace.
default_registry contains the following policies:
| policy category | policy | role |
|---|---|---|
rtti |
std_rtti |
provides type information for classes and objects |
vptr |
vptr_vector |
stores vptrs in an indexed collection |
type_hash |
fast_perfect_hash |
hash type id to an index in a vector |
error_handler |
default_error_handler |
handles errors |
output |
stderr_output |
prints diagnostics to |
if
BOOST_OPENMETHOD_ENABLE_RUNTIME_CHECKS
is defined, default_registry also contains the runtime_checks policy. This
enables extra validations during method dispatch, which can detect missing class
registrations that could not be caught by initialize.
The library provides another predefined registry: indirect_registry. It is
useful when shared libraries are dynamically loaded at runtime, and add methods
and overriders across program and shared library boundaries. See the section
about shared_libraries.adoc[shared libraries].
Registries can be created from scratch, using the registry template. Here is
the definition of default_registry, copied from
<boost/openmethod/registry.hpp>:
struct default_registry
: registry<
policies::std_rtti,
policies::vptr_vector, policies::fast_perfect_hash,
policies::default_error_handler,
policies::stderr_output
#ifdef BOOST_OPENMETHOD_ENABLE_RUNTIME_CHECKS
,
policies::runtime_checks
#endif
> {
};
When defining a new registry, it is recommended to define a new class, derived
from registry<…>, rather than via a typedef, which would create excessively
long symbol names and make debugging harder.
A registry can calso be created by copying an existing registry’s policies,
using the with and without nested templates. For example,
indirect_registry is a tweak of default_registry:
struct indirect_registry : default_registry::with<policies::indirect_vptr> {};
Policies are implemented as unary
Boost.MP11
quoted metafunctions. A policy is an ordinary class that contains a nested
class template, called fn which is instantiated by the registry, passing
itself as the template argument. The reason for this mechanism is to allow
policies that have static data members to give each registry its own copy.
vptr_vector, for example, stores v-table pointers in a std::vector. If it is
used in two different registries, it needs to use two different vectors, one for
each registry.