Миксины

Миксин - это специальный элемент в теле программы, который состоит из ключевого слова mixin и выражения в (). Выражение должно быть constexpr массивом char8 элементов, который содержит текст фрагмента программы. Этот текст компилируется так же, как и основной текст исходных файлов.

Текст фрагмента кода mixin можно сгенерировать на этапе компиляции при помощи constexpr вычислений, в том числе с помощью constexpr функций. Это позволяет, например, создавать такой код, который не возможно создать при помощи макросов или шаблонов.

Контексты использования mixin

mixin можно использовать в пространствах имён:

mixin( "fn Foo() : i32 { return 52; }" ); // создастся глобальная функция Foo

namespace Some
{
    mixin( "fn Bar() : f32 { return 0.0f; }" ); // создастся функция Some::Bar
}

Также mixin можно использовать внутри структур и классов:

struct S
{
    // Создаём пару полей и объявление метода
    mixin( "i32 x; f64 y; fn Foo(this) : u32;" );
}
fn Foo()
{
    var S s{ .x= 67, .y= 0.124 };
    s.Foo();
}

mixin в блоках также возможны:

fn Foo() : i32
{
    mixin( " return 123; " );
}

mixin в имени типа:

type T= mixin(mixin_text);
auto mixin_text= "[ i32, 4 ]";

mixin в качесве выражения:

fn Foo( i32 x, i32 y ) : i32
{
    return mixin( "x + y" ) * 2;
}

Ограничения mixin

import внутри mixin не возможен.

В mixin нельзя объявлять макросы. Но можно использовать макросы, доступные в файле, где используется этот mixin.

Можно объявить mixin в результате раскрытия mixin. Но глубина раскрытия ограничена небольшим числом, что делает в том числе невозможным рекурсию раскрытия mixin.

Все mixin вне шаблонов и все mixin в рамках одного шаблона класса раскрываются в два этапа - сначала вычисляются выражения во всех mixin, а уже только потом добавляются символы из них. Из-за этой особенности нельзя использовать в mixin выражениях символы, объявляемые при раскрытии других mixin.