Draft:YOMM2

The YOMM2 library implements open multi-methods for C++17 and above.

Bjarne Stroustrup gave CLOS open multi-methods as an example of a feature from another language that he likes. He talks about them in Design and Evolution of C++, and suggests a syntax. Later, he and his students co-wrote a series of papers on the subject.

Overview
The declare_method macro declares a method. It is equivalent to defgeneric in the Common Lisp Object System. It takes a return type, a method name, and a list of types, some of which are marked as virtual (using the virtual_ decorator).

The define_method macro adds definitions, or specializations, to a previously declared method. It is equivalent to defgeneric in CLOS. It takes a return type, a method name, a parameter list, and is followed by a function body.

When a method is called, the dynamic types of the arguments corresponding to the virtual parameters of the method are used to select the appropriate definition to call, from the set of registered definitions. The selection is made according to the same rules as overload resolution, albeit it happens when the program is run, not compiled.

All classes potentially involved in a method call must be registered via the macro use_classes.

The yorel::yomm2::update_methods must be called before making calls to methods.

YOMM2 also provides a core interface, which does not use macros, and thus makes it possible to use the library in conjunction with templates.

Design
The library is inspired by the paper "Open Multi-Methods for C++", by Peter Pirkelbauer, Yuryi Solodkyy and Bjarne Stroustrup .

At compilation time, YOMM2 uses macro and template meta-programming to collect information about classes, methods, and method definitions, and stores it in static objects.

At initialization time, YOMM2 calculates the inheritance relationships between the registered classes, and, for each method, which definition should be called for every possible tuple of virtual arguments. For each class, it builds a method table. For uni-methods, it contains a pointer to the applicable definition. For multi-methods, it contains a pointer to a multi-dimensional dispatch table, which is free of redundancies. YOMM2 also finds a perfect hash function for the typeid of the registered classes, and uses it to build a hash table that maps typeids to method tables.

At dispatch time, YOMM2 reads the dynamic typeid of the virtual arguments, and uses the hash table to retrieve the corresponding method tables. In release builds, a method call is very fast: calling a uni-method is almost as fast as calling an equivalent virtual function. In debug builds, YOMM2 performs various checks to detect and clearly report errors such as missing or ambiguous definitions, or missing class registrations.