Перед type можно написать вызовы одной и нескольких метафункций, которые добавляют несуществующие методы в определение класса (@ordered, @copyable), проверяют требования к классу (@interface, @struct) или полностью меняют определение (@enum).
Метафункция|Назначение
-|-
@interface|проверяет, что класс содержит только виртуальные функции без определения и не содержит полей
@struct|делает все элементы класса открытыми и проверяет, что нет виртуальных функций и определяемых пользователем операций =
@enum|определяет класс, объекты которого могут принимать только указанные значения, и функцию ``to_string`` для него
@flag_enum|определяет класс, объекты которого могут хранить множества из указанных значений, ``none`` для пустого множества, функции ``to_string``, ``has``, ``set``, ``clear``, ``get_raw_value`` и операции ``| & ^``
@union|определяет класс, объекты которого могут хранить только одно из указанных полей, и функции ``is_$$$``, ``$$$``, ``set_$$$``, где ``$$$`` -- название поля
@polymorphic_base|проверяет, что класс не содержит операции копирования или перемещения, добавляет виртуальный деструктор, если его нет
@ordered\
@weakly_ordered\
@partially_ordered|добавляет соответствующую операцию сравнения или проверяет тип её результата
@copyable|проверяет наличие операций присваивания/копирования и добавляет их при отсутствии
@basic_value|проверяет, что класс не содержит защищенных или виртуальных функций, добавляет операции присваивания/копирования и конструктор по умолчанию (без параметров), если их нет
@value\
@weakly_ordered_value\
@partially_ordered_value|включает @basic_value и соответствующую операцию сравнения
@print|отладочная печать типа
Преобразование в С++ выполняет cpp2front, поэтому собственные метафункции определяются в файле sources/cpp2front/reflect.h2. После добавления определения метафункции и ее вызова в apply_metafunctions транслятор нужно пересобрать и переустановить в MinIDE, используя Makefile в папке sources/cpp2front.
Пример метафункции:
```
interface: (inout t: meta::type_declaration) = {
has_dtor := false;
t.require( t.get_member_objects().size()==0, "interfaces may not contain data objects");
for t.get_member_functions() do (inout m) {
m.require( !m.is_copy_or_move(), "interfaces may not copy or move; consider a virtual clone() instead");
m.require( !m.has_initializer(), "interface functions must not have a function body; remove the '=' initializer");
m.require( m.make_public(), "interface functions must be public");
m.default_to_virtual();
has_dtor |= m.is_destructor();
}
if !has_dtor {
t.add_member( "operator=: (virtual move this) = { }");
}
}
```
Для определения типа доступны следующие методы
Методы|Тип|Назначение
--|--|--
is_polymorphic|(this) -> bool|есть виртуальные методы
is_final|(this) -> bool|является финальным
make_final|(inout this) -> bool|сделать финальным
get_members|(this) -> std::vector<declaration>|получить коллекцию элементов
get_member_functions|(this) -> std::vector<function_declaration>|получить коллекцию методов
get_member_objects|(this) -> std::vector<object_declaration>|получить коллекцию полей
get_member_types|(this) -> std::vector<type_declaration>|получить коллекцию типов, определенных внутри класса
add_member|(inout this, source: std::string_view)|добавить элемент
disable_member_function_generation|(inout this)|не генерировать операции копирования/присваивания
remove_all_members|(inout this)|удалить все элементы
remove_marked_members|(inout this)|удалить помеченные элементы
Для всех элементов (declaration) доступны следующие методы
Методы|Тип|Назначение
--|--|--
is_public|(this) -> bool|открытый элемент
is_protected|(this) -> bool|защищенный элемент
is_private|(this) -> bool|закрытый элемент
is_default_access|(this) -> bool|не указан доступ
make_public|(this) -> bool|сделать открытым, если возможно
make_protected|(this) -> bool|сделать защищенным
make_private|(this) -> bool|сделать закрытым
name|(this) -> std::string_view|получить имя
has_initializer|(this) -> bool|у элемента есть инициализатор
is_global|(this) -> bool|является глобальным (статическим элементом?)
is_function|(this) -> bool|является функцией
is_object|(this) -> bool|является полем или базовым объектом
is_base_object|(this) -> bool|является базовым объектом
is_member_object|(this) -> bool|является полем
is_type|(this) -> bool|является типом
is_namespace|(this) -> bool|является пространством имен
is_alias|(this) -> bool|является псевдонимом
is_type_alias|(this) -> bool|является псевдонимом типа
is_namespace_alias|(this) -> bool|является псевдонимом пространства имен
is_object_alias|(this) -> bool|является псевдонимом объекта
mark_for_removal_from_enclosing_type|(inout this)|пометить для удаления
get_parent|(this) -> declaration|получить базовый тип