P0707 R0: Metaclasses – Sutter 8
• Generate functions: Default declarations and implementations for functions that all classes conforming
to the metaclass must have, such as “a
value
always has copy and move, and memberwise definitions
are generated by default if copy and move are not explicitly written by hand.”
• Perform transformations: Changes to declared entities, such as “an
rt_interface
must have an
HRE-
SULT
return type, and a non-
void
return type must be changed to an additional
[[out,
retval]]
pa-
rameter instead,” or “a
variant
type replaces all of the data members declared in the protoclass with
an opaque buffer in the fully defined class.”
Notes One result is that metaclasses provide “generalized opt-in” for generated functions. A metaclass re-
places the built-in
class
special member function generation rules because the metaclass is taking
over responsibility for all generation.
C++ provides only a few “special” generated functions for all classes, and more are desirable (e.g.,
comparisons). They are difficult to manage and extend because today C++ has only a monolithic uni-
verse of all classes, with no way to name subsets of classes. So, each compiler-generated “special
member function” has to be generated based on a general heuristic that must work well enough for
all conceivable classes to decide whether the function would likely be desired. But no heuristic is
correct for all types, so this led to bugs when a special function was generated or omitted inappro-
priately (the heuristic failed), which led to the need for ways to “opt back out” and turn off a gener-
ated function when not desired (
=delete
) or to “opt back in” and use the default function semantics
when the heuristic did not generate them (manual declaration followed by
=default
). Any new gen-
erated functions, such as comparisons, would need their own heuristics and face the same problems
if the same rule is forced to apply to all possible classes.
Metaclasses provide a way to name a group of classes (a subset of the universe of all classes), and
an extensible way to give that subset appropriate generated functions. Because the generated func-
tions are provided by the metaclass, the metaclass name is the natural “opt-in” to get everything it
provides. In turn, because generated functions are provided exactly and only when asked for, meta-
classes remove the need to reinstate/suppress them – because we opted in, the functions the meta-
class generates cannot logically be suppressed because if we didn’t want them we wouldn’t have
opted into the metaclass (thus no need for
=delete
for generated functions), and because they are
never suppressed by a heuristic we never need to reinstate them (thus no need to
=default
them).
Of course,
=default
and
=delete
are still useful for other things, such as a convenient way to get
default bodies (see P0515) or to manage overload sets, respectively. The point here is only that,
when using metaclasses, they are no longer needed to override an overly general heuristic that
guesses wrong.
In a metaclass the following defaults apply, and are applied in metaclass finalization:
• Functions are public by default, and data members are private by default (if not already specified).
• The only implicitly generated function is a public nonvirtual default destructor (if not declared).