boost::openmethod::register_classes

Find the classes taking part in dispatch by reflection, and register them (C++26 and above).

Synopsis

Declared in <boost/openmethod/core.hpp>

template<auto Groups...>
class register_classes;

Description

Requires C++26 reflection (P2996): a compiler that implements it, and the flag that turns it on ‐ ‐freflection with GCC 16. Without it this class template does not exist: BOOST_OPENMETHOD_HAS_REFLECTION is 0, and classes are registered with use_classes or BOOST_OPENMETHOD_CLASSES. BOOST_OPENMETHOD_REGISTER_CLASSES wraps this class in a macro that expands to a no‐op under C++17.

register_classes is a registrar class that finds the classes taking part in dispatch by reflection, and adds them to one or more registries. It makes use_classes unnecessary in most cases.

The arguments are groups of reflections, each written in braces ‐ or, for a group of one, as the reflection itself. A group holds one kind of reflection, and the groups come in this order; each one is optional, and omitting all of them is the common case:

  • Namespaces to scan: {ˆˆapp, ˆˆzoo}, {ˆˆ::}.

  • Classes to register: {ˆˆAnimal}. They are registered whether a method dispatches on them or not, and they are extra roots for the scan, which registers the classes it finds deriving from them. A listed class must be complete.

  • Registries to register the classes in: {ˆˆmy_registry}. Each one receives the registration. The default is BOOST_OPENMETHOD_DEFAULT_REGISTRY.

register_classes<^^app, ^^my_registry>
register_classes<{^^app, ^^zoo}, {^^r1, ^^r2}>
register_classes<{^^Animal, ^^Dog}>
register_classes<^^my_registry>
register_classes<>

A group holding two kinds of reflection is an error, and so is a group out of order. Braces around a single reflection change nothing: register_classes<ˆˆapp> and register_classes<{ˆˆapp}> are the same registration.

The scan covers the listed namespaces, the namespaces nested in them, and the classes nested in the classes it declares, except std and boost: walking those would cost a great deal and find nothing, as a method cannot be declared on a class the program has never heard of. The exclusion applies to recursion only, so a class in std or boost is registered by listing the namespace it is in. The scan never goes through an alias: a namespace alias is not entered, and a type alias registers the class it names but is not walked into. The scan finds the methods of each target registry and collects the classes they dispatch on; those, and the listed classes, are the roots. It registers the roots, and every class it finds that derives from one of them. A base class that no method dispatches on, and that is not listed, is not registered: it could never be selected on.

A class between a registered class and a root is registered too, wherever it is declared: in a namespace the scan does not enter, or as a specialization of a class template, which the scan cannot find on its own. The namespaces decide where the derived classes are looked for, not which bases are recorded; and each class is recorded with every registered class above it, so that a registration stands on its own, whatever another one, in another translation unit, registers alongside it.

If no namespace is given, the global namespace is scanned ‐ whatever the other groups hold, and for BOOST_OPENMETHOD_REGISTER_CLASSES too. Name a namespace to scan only that one.

The scan runs when the registrar is instantiated, which current compilers do at the end of the translation unit: it sees the whole file, wherever the registrar sits. The standard promises less. A class or a method the scan would select, declared after the registrar in the same translation unit, makes the program ill‐formed, no diagnostic required. Put the registrar after the declarations it is meant to find, at the bottom of the file.

A method is found through any namespace member that names its method specialization: the alias BOOST_OPENMETHOD declares for it, a using declaration written by hand, or any of its registrar objects ‐ the object BOOST_OPENMETHOD_OVERRIDE creates, or one written by hand. None of those requires the method to have an overrider. A core interface method whose method<...> type is spelled out in full at every use, with neither a using declaration nor an overrider, is named by nothing and is not found; its classes must be registered with use_classes. A method's return type is not a root: a covariant return type is registered like any other class, when it derives from a root, or when it is listed.

Virtual and multiple inheritance are supported. Unlike use_classes, which rejects it, repeated inheritance is not an error here: a class is recorded under the bases it reaches unambiguously through public inheritance, and a base it inherits more than once, which no reference to it can be converted to, is left out of its list. A class with no registered class above it is not registered at all.

Member Functions

Name

Description

register_classes [constructor]

Register the selected classes in each target registry.

Template Parameters

Name

Description

Groups

Braced groups of reflections: namespaces, classes, registries, in that order.

See Also

Created with MrDocs