В D функциям можно назначить атрибуты различными способами.
Давайте рассмотрим пару встроенных атрибутов,
а также атрибуты, определяемые пользователем.
Напомним, что также существуют встроенные атрибуты
@safe@
, @system
и @trusted
, уже упомянутые
в первой главе.
@property
Функция, помеченная атрибутом @property
,
снаружи выглядит как обычный член:
struct Foo {
@property bar() { return 10; }
@property bar(int x) { writeln(x); }
}
Foo foo;
writeln(foo.bar); // на самом деле,
// вызывает foo.bar()
foo.bar = 10; // вызывает foo.bar(10);
@nogc
Когда компилятор D встречает функцию, помеченную как @nogc
,
он удостоверится, что в контексте такой функции не производится
никаких выделений памяти сборщиком мусора.
@nogc
-функция может вызывать только другие @nogc
-функции.
void foo() @nogc {
// ОШИБКА:
auto a = new A;
}
Любой функции и любому типу в D можно назначить атрибуты, определяемые пользователем:
struct Bar { this(int x) {} }
struct Foo {
@("Hello") {
@Bar(10) void foo() {
...
}
}
}
Любой тип, как встроенный, так и определяемый пользователем,
можно использовать как атрибут функции.
В данном примере функции foo()
назначается два
атрибута: "Hello"
(тип string
) и Bar
(тип Bar
со значением 10
). Чтобы получить
список атрибутов функции, используйте встроенный
типаж __traits(getAttributes, Foo)
,
который возвращает TypeTuple
.
UDA позволяют обогатить обобщённый код, открывая новую метрику для типов, что помогает генераторам кода, работающим во время компиляции, подстроиться под конкретный тип.