GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||
GeezerVison is showing dlang.org — Attributes - D Programming Language Language Reference
Report a bug
If you spot a problem with this page, click here to create a GitHub issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page.
Requires a signed-in GitHub account. This works well for small changes.
If you'd like to make larger changes you may want to consider using
a local clone.
Attributes Contents
GrammarAttributeSpecifier:
Attribute :
Attribute DeclarationBlock
Attribute:
AlignAttribute
AtAttribute
DeprecatedAttribute
FunctionAttributeKwd
LinkageAttribute
Pragma
VisibilityAttribute
abstract
auto
const
final
__gshared
extern
immutable
inout
override
ref
__rvalue
scope
shared
static
synchronized
FunctionAttributeKwd:
nothrow
pure
AtAttribute:
@ disable
@ __future
@ __ctfe
@ nogc
@ live
Property
@ safe
@ system
@ trusted
UserDefinedAttribute
Property:
@ property
DeclarationBlock:
DeclDef
{ DeclDefsopt }
Attributes are a way to modify one or more declarations. The general forms are: attribute declaration; // affects the declaration attribute: // affects all declarations until the end of // the current scope declaration; declaration; ... attribute // affects all declarations in the block { declaration; declaration; ... } Function attributes @nogc, nothrow and pure do not propagate inside aggregate declarations. const pure @safe { int i; // function attributes ignored for non-functions void f(); // const attribute ignored for free function struct S { int i; void f(); // pure ignored inside struct } } static assert(is(typeof(i) == const int)); static assert(is(typeof(&f) == void function() pure @safe)); static assert(is(typeof(S.i) == const int)); static assert(is(typeof(&S().f) == void delegate() const @safe)); See also: core.attribute for other compiler-recognized attributes. Linkage AttributeLinkageAttribute:
extern ( LinkageType )
extern ( C ++ , )
extern ( C ++ , QualifiedIdentifier )
extern ( C ++ , NamespaceList )
extern ( C ++ , class )
extern ( C ++ , struct )
LinkageType:
C
C ++
D
Windows
System
Objective - C
NamespaceList:
ConditionalExpression
ConditionalExpression ,
ConditionalExpression , NamespaceList
D provides an easy way to call C functions and operating system API functions, as compatibility with both is essential. The LinkageType is case sensitive, and is meant to be extensible by the implementation (they are not keywords). C and D must be supplied, the others are what makes sense for the implementation. C++ offers limited compatibility with C++, see the Interfacing to C++ documentation for more information. Objective-C offers compatibility with Objective-C, see the Interfacing to Objective-C documentation for more information. System is the same as Windows on Windows platforms, and C on other platforms. Implementation Note: for Win32 platforms, Windows should exist. C function calling conventions are specified by: extern (C): int foo(); // call foo() with C conventionsNote that extern(C) can be provided for all types of declarations, including struct or class, even though there is no corresponding match on the C side. In that case, the attribute is ignored. This behavior applies for nested functions and nested variables as well. However, for static member methods and static nested functions, adding extern(C) will change the calling convention, but not the mangling. D conventions are: extern (D):
Windows API conventions are: extern (Windows): void *VirtualAlloc( void *lpAddress, uint dwSize, uint flAllocationType, uint flProtect ); The Windows convention is distinct from the C convention only on Win32 platforms, where it is equivalent to the stdcall convention. Note that a lone extern keyword is used as a storage class. C++ NamespacesThe linkage form extern (C++, QualifiedIdentifier) creates C++ declarations that reside in C++ namespaces. The QualifiedIdentifier specifies the namespaces. extern (C++, N) { void foo(); } refers to the C++ declaration: namespace N { void foo(); }
and can be referred to with or without qualification: foo(); N.foo(); Namespaces create a new named scope that is imported into its enclosing scope. extern (C++, N) { void foo(); void bar(); } extern (C++, M) { void foo(); } void main() { bar(); // ok //foo(); // error - N.foo() or M.foo() ? M.foo(); // ok } Multiple dotted identifiers in the QualifiedIdentifier create nested namespaces: extern (C++, N.M) { extern (C++) { extern (C++, R) { void foo(); } } } N.M.R.foo(); refers to the C++ declaration: namespace N { namespace M { namespace R { void foo(); } } }
align AttributeAlignAttribute:
align ( default )
align
align ( AssignExpression )
Specifies the alignment of:
align(default) (re)sets it to the default, which matches the default member alignment of the companion C compiler. align by itself is the same as align(default). struct S { align(default): // same as `align:` byte a; // placed at offset 0 int b; // placed at offset 4 long c; // placed at offset 8 } static assert(S.alignof == 8); static assert(S.c.offsetof == 8); static assert(S.sizeof == 16); The AssignExpression specifies the alignment which matches the behavior of the companion C compiler when non-default alignments are used. It must be a non-negative power of 2. A value of 1 means that no alignment is done; fields are packed together. struct S { align (1): byte a; // placed at offset 0 int b; // placed at offset 1 long c; // placed at offset 5 } static assert(S.alignof == 1); static assert(S.c.offsetof == 5); static assert(S.sizeof == 13); The natural alignment of an aggregate is the maximum alignment of its fields. It can be overridden by setting the alignment outside of the aggregate. align (2) struct S { align (1): byte a; // placed at offset 0 int b; // placed at offset 1 long c; // placed at offset 5 } static assert(S.alignof == 2); static assert(S.c.offsetof == 5); static assert(S.sizeof == 14); Setting the alignment of a field aligns it to that power of 2, regardless of the size of the field. struct S { byte a; // placed at offset 0 align (4) byte b; // placed at offset 4 align (16) short c; // placed at offset 16 } static assert(S.alignof == 16); static assert(S.c.offsetof == 16); static assert(S.sizeof == 32); The AlignAttribute is reset to the default when entering a function scope or a non-anonymous struct, union, class, and restored when exiting that scope. It is not inherited from a base class. See also: Struct Layout. GC CompatibilityDo not align references or pointers that were allocated using NewExpression on boundaries that are not a multiple of size_t. The garbage collector assumes that pointers and references to GC allocated objects will be on size_t byte boundaries. struct S { align(1): byte b; int* p; } static assert(S.p.offsetof == 1); @safe void main() { S s; s.p = new int; // error: can't modify misaligned pointer in @safe code } Undefined Behavior: If any pointers and references to GC
allocated objects are not aligned on size_t byte boundaries.
deprecated AttributeDeprecatedAttribute:
deprecated
deprecated ( AssignExpression )
It is often necessary to deprecate a feature in a library, yet retain it for backwards compatibility. Such declarations can be marked as deprecated, which means that the compiler can be instructed to produce an error if any code refers to deprecated declarations: deprecated { void oldFoo(); } oldFoo(); // Deprecated: function test.oldFoo is deprecated Optionally a string literal or manifest constant can be used to provide additional information in the deprecation message. deprecated("Don't use bar") void oldBar(); oldBar(); // Deprecated: function test.oldBar is deprecated - Don't use bar Calling CTFE-able functions or using manifest constants is also possible. import std.format; enum message = format("%s and all its members are obsolete", Foobar.stringof); deprecated(message) class Foobar {} deprecated(format("%s is also obsolete", "This class")) class BarFoo {} void main() { auto fb = new Foobar(); // Deprecated: class test.Foobar is deprecated - Foobar // and all its members are obsolete auto bf = new BarFoo(); // Deprecated: class test.BarFoo is deprecated - This // class is also obsolete } Implementation Note: The compiler should have a switch specifying if deprecated should be ignored, cause a warning, or cause an error during compilation. @__future attributeThe @__future attribute is used to mark a new symbol which could cause a name clash in another module. The other module using a symbol with the same name will continue to compile as before but will show a deprecation message. The message indicates that the new symbol will break the existing code in future, and the other module should be updated. Note: Currently only methods that implicitly override a @__future base class
method show a deprecation message.
See DIP1007 for details. @__ctfe attributeThe @__ctfe attribute ensures a function is only called with CTFE, disabling object code generation. It will bypass any restrictions on code generation sourced from command-line flags. An @__ctfe function cannot be called in a runtime context, and taking its address at runtime is an error: int add(int a) @__ctfe => a + 2; void main() { static int w = add(1); // OK int x = add(1); // Error: function marked with @__ctfe cannot be called at runtime auto fp = &add; // Error: cannot take address of function marked with @__ctfe } Note: Virtual methods cannot be marked as @__ctfe due to interactions with inheritance.
Visibility AttributesVisibilityAttribute:
export
package
package ( QualifiedIdentifier )
private
protected
public
Visibility is an attribute that is one of private, package, protected, public, or export. They may be referred to as protection attributes in documents predating DIP22. Visibility participates in symbol name lookup. export Attributeexport means that a symbol can be accessed from outside the executable, shared library, or DLL. The symbol is said to be exported from where it is defined in an executable, shared library, or DLL, and imported by another executable, shared library, or DLL. export applied to the definition of a symbol will export it. export applied to a declaration of a symbol will import it. A variable is a definition unless extern is applied to it. export int x = 3; // definition, exporting `x` export int y; // definition, exporting `y` export extern int z; // declaration, importing `z` export __gshared h = 3; // definition, exporting `h` export __gshared i; // definition, exporting `i` export extern __gshared int j; // declaration, importing `j` A function with a body is a definition, without a body is a declaration. export void f() { } // definition, exporting `f` export void g(); // declaration, importing `g` In Windows terminology, dllexport means exporting a symbol from a DLL, and dllimport means a DLL or executable is importing a symbol from a DLL. package Attributepackage extends private so that package members can be accessed from code in other modules that are in the same package. If no identifier is provided, this applies to the innermost package only, or defaults to private if a module is not nested in a package. package may have an optional parameter in the form of a dot-separated identifier list which is resolved as the qualified package name. The package must be either the module's parent package or one of its ancestors. If this parameter is present, the symbol will be visible in the specified package and all of its descendants. private AttributeSymbols with private visibility can only be accessed from within the same module. Private member functions are implicitly final and cannot be overridden. protected Attributeprotected only applies inside classes (and templates as they can be mixed in) and means that a symbol can only be seen by members of the same module, or by a derived class. If accessing a protected instance member through a derived class member function, that member can only be accessed for the object instance which can be implicitly cast to the same type as ‘this’. protected module members are illegal. public Attributepublic means that any code within the executable can see the member. It is the default visibility attribute. Mutability Attributesconst AttributeThe const type qualifier changes the type of the declared symbol from T to const(T), where T is the type specified (or inferred) for the introduced symbol in the absence of const. const int foo = 7; static assert(is(typeof(foo) == const(int))); const double bar = foo + 6; static assert(is(typeof(bar) == const(double))); class C { const void foo(); const { void bar(); } void baz() const; } pragma(msg, typeof(C.foo)); // const void() pragma(msg, typeof(C.bar)); // const void() pragma(msg, typeof(C.baz)); // const void() static assert(is(typeof(C.foo) == typeof(C.bar)) && is(typeof(C.bar) == typeof(C.baz))); See also: Methods Returning a Qualified Type. immutable AttributeThe immutable attribute modifies the type from T to immutable(T), the same way as const does. See: inout AttributeThe inout attribute modifies the type from T to inout(T), the same way as const does. Shared Storage Attributesshared AttributeSee shared. __gshared AttributeBy default, non-immutable global declarations reside in thread local storage. When a global variable is marked with the __gshared attribute, its value is shared across all threads. int foo; // Each thread has its own exclusive copy of foo. __gshared int bar; // bar is shared by all threads. __gshared may also be applied to member variables and local variables. In these cases, __gshared is equivalent to static, except that the variable is shared by all threads rather than being thread local. class Foo { __gshared int bar; } int foo() { __gshared int bar = 0; return bar++; // Not thread safe. } Warning: Unlike the shared attribute, __gshared provides no safeguards against data races or other multi-threaded synchronization issues. It is the responsibility of the programmer to ensure that access to variables marked __gshared is synchronized correctly. __gshared is disallowed in @safe code. synchronized AttributeSee Synchronized Methods. @disable AttributeThe following declarations can be disabled using the @disable attribute:
Use of a disabled declaration will cause a compile time error. Best Practices: Use @disable to explicitly disallow certain
operations or overloads at compile time, rather than relying on a function generating a
runtime error.
@disable int x; @disable void foo(); void foo(int); void main() { x++; // error, x is disabled foo(); // error, foo is disabled foo(5); // OK, not disabled } A user-defined type cannot be disabled, though a constructor can be. In particular:
@safe, @trusted, and @system AttributesSee Function Safety. System VariablesVariables marked @system cannot be accessed from @safe code. @system int* p; struct S { @system int i; } void main() @safe { int x = *p; // error with `-preview=systemVariables`, deprecation otherwise S s; s.i = 0; // ditto } Function Attributes@nogc AttributeSee No-GC Functions. @property AttributeSee Property Functions. nothrow AttributeSee Nothrow Functions. pure AttributeSee Pure Functions. ref AttributeSee ref Storage Class. return Attribute__rvalue Attributestatic AttributeThe static attribute applies to types, functions and variables. static is ignored when applied to other declarations. Inside an aggregate type, a static declaration does not apply to a particular instance of an object, but to the type of the object. In other words, it means there is no this reference. class Foo { static int x; static int bar() { return x; } int foobar() { return 7; } } Foo.x = 6; // no instance needed assert(Foo.bar() == 6); //Foo.foobar(); // error, no instance of Foo Foo f = new Foo; assert(f.bar() == 6); assert(f.foobar() == 7); Static methods are never virtual. Static data has one instance per thread, not one per object. A static nested function or type cannot access variables in the parent scope. Inside a function, a static local variable persists after the function returns. Static does not have the additional C meaning of being local to a file. Use the private attribute in D to achieve that. For example: module foo; int x = 3; // x is global private int y = 4; // y is local to module foo auto AttributeThe auto attribute is used when there are no other attributes and type inference is desired. auto i = 6.8; // declare i as a double For functions, the auto attribute means return type inference. See Auto Functions. scope AttributeThe scope attribute signifies a variable's pointer values will not escape the scope that the variable is declared in. If the variable has a type that does not contain any indirections, the scope attribute is ignored. When applied to a global variable, scope is also ignored, since there is no scope larger than global scope that pointers could escape to. scope int* x; // scope ignored, global variable void main() { // scope static int* x; // cannot be both scope and static scope float y; // scope ignored, no indirections scope int[2] z; // scope ignored, static array is value type scope int[] w; // scope dynamic array } When applied to a local variable with a type that has indirections, its value may not be assigned to a variable with longer lifetime:
Other operations implicitly assigning them to variables with longer lifetime are also disallowed:
Note: escape analysis is only done in @safe code. The -preview=dip1000 switch
must also be enabled.
The scope attribute is part of the variable declaration, not the type, and it only applies to the first level of indirection. For example, it is impossible to declare a variable as a dynamic array of scope pointers, because scope only applies to the .ptr of the array itself, not its elements. scope affects various types as follows:
struct S { string str; // note: string = immutable(char)[] string* strPtr; } string escape(scope S s, scope S* sPtr, scope string[2] sarray, scope string[] darray) { return s.str; // invalid, scope applies to struct members return *s.strPtr; // valid, scope struct member is dereferenced return sPtr.str; // valid, struct pointer is dereferenced return *sPtr.strPtr; // valid, two pointers are dereferenced return sarray[0]; // invalid, scope applies to static array elements return sarray[1]; // invalid, ditto return darray[0]; // valid, scope applies to array pointer, not elements } Scope ValuesA "scope value" is the value of a scope variable, or a generated value pointing to stack allocated memory. Such values are generated by slicing a static array or creating a pointer to a variable that is (or may be) allocated on the stack:
The variadic parameter from Typesafe Variadic Functions is also a scope value, since the arguments are passed on the stack. When a local variable is assigned a scope value, it is inferred scope, even when the variable has an explicit type and does not use the auto keyword. @safe: ref int[2] identity(return ref int[2] x) {return x;} int* escape(int[2] y, scope int* z) { int x; auto xPtr = &x; // inferred `scope int*` int[] yArr = identity(y)[]; // inferred `scope int[]` int* zCopy = z; // inferred `scope int*` return zCopy; // error } void variadic(int[] a...) { int[] x = a; // inferred `scope int[]` } void main() { variadic(1, 2, 3); } struct S { int x; // this method may be called on a stack-allocated instance of S void f() @safe { int* p = &x; // inferred `scope int* p` int* q = &this.x; // equivalent } } @safe int[] foo() { int[3] arr = [1,2,3]; int[] slice = arr[]; // slice picks up scope attribute return slice; // error, returning scope variable `slice` is not allowed } int[] slice; @safe void abc() { int[3] arr = [1,2,3]; slice = arr[]; // error, assigning address of variable `arr` to `slice` with longer lifetime } Scope Parameters are treated the same as scope local variables, except that returning them is allowed when the function has Function Attribute Inference. In that case, they are inferred as Return Scope Parameters. scope Class InstancesWhen used to allocate a class instance directly, a scope variable signifies the RAII (Resource Acquisition Is Initialization) protocol. This means that the destructor for an object is automatically called when the reference to it goes out of scope. The destructor is called even if the scope is exited via a thrown exception, thus scope is used to guarantee cleanup. When a class is constructed with new and assigned to a local scope variable, it may be allocated on the stack and permitted in a @nogc context. If there is more than one scope class variable going out of scope at the same point, then the destructors are called in the reverse order that the variables were constructed. Assignment to a scope variable with class type, other than initialization, is not allowed, because that would complicate proper destruction of the variable. import core.stdc.stdio : puts; class C { ~this() @nogc { puts(__FUNCTION__); } } void main() @nogc { { scope c0 = new C(); // allocated on the stack scope c1 = new C(); //c1 = c0; // Error: cannot rebind scope variables // destructor of `c1` and `c0` are called here in that order } puts("bye"); } OOP Attributesabstract AttributeAn abstract class must be overridden by a derived class. Declaring an abstract member function makes the class abstract. final Attribute
override AttributeSee Virtual Functions. @mustuse AttributeThe @mustuse attribute is a compiler-recognized UDA defined in the D runtime module core.attribute. An expression is considered to be discarded if and only if either of the following is true:
It is a compile-time error to discard an expression if all of the following are true:
"Assignment expression" means either a simple assignment expression or an assignment operator expression. "Increment expression" means a UnaryExpression or PostfixExpression whose operator is ++. "Decrement expression" means a UnaryExpression or PostfixExpression whose operator is --. It is a compile-time error to attach @mustuse to a function declaration or to any aggregate declaration other than a struct or union declaration. The purpose of this rule is to reserve such usage for possible future expansion. User-Defined AttributesUserDefinedAttribute:
@ ( TemplateArgumentList )
@ TemplateSingleArgument
@ Identifier ( NamedArgumentListopt )
@ TemplateInstance
@ TemplateInstance ( NamedArgumentListopt )
User-Defined Attributes (UDAs) are compile-time annotations that can be attached to a declaration. These attributes can then be queried, extracted, and manipulated at compile time. There is no runtime component to them. A user-defined attribute is defined using:
@3 int a; // value attribute @("string", 7) int b; // multiple values // using compile-time constant enum val = 3; @val int a2; // has same attribute as `a` enum Foo; @Foo int c; // type name attribute struct Bar { int x; } @Bar() int d; // type instance attribute @Bar(3) int e; // type instance attribute using initializer For e, the attribute is an instance of struct Bar which is statically initialized using its argument. If there are multiple UDAs in scope for a declaration, they are concatenated: @(1)
{
@(2) int a; // has UDAs (1, 2)
@("string") int b; // has UDAs (1, "string")
}
A function parameter can have a UDA. Parameters do not inherit UDAs from outside the parameter list. @2 void f(@3 int p) { pragma(msg, __traits(getAttributes, p)); // prints AliasSeq!(3) } __traits(getAttributes)UDAs can be extracted into a compile-time sequence using __traits: @('c') string s;
pragma(msg, __traits(getAttributes, s)); // prints AliasSeq!('c')
If there are no user-defined attributes for the symbol, an empty sequence is returned. The result can be used just like any compile-time sequence - it can be indexed, passed as template parameters, etc. enum e = 7; @("hello") struct SSS { } @(3) { @(4) @e @SSS int foo; } alias TP = __traits(getAttributes, foo); pragma(msg, TP); // prints AliasSeq!(3, 4, 7, (SSS)) pragma(msg, TP[2]); // prints 7 Any types in the sequence can be used to declare things: TP[3] a; // a is declared as an SSS
The attribute of the type name is not the same as the attribute of the variable: pragma(msg, __traits(getAttributes, a)); // prints AliasSeq!() pragma(msg, __traits(getAttributes, typeof(a))); // prints AliasSeq!("hello") UsageOf course, the real value of UDAs is to be able to create user-defined types with specific values. Having attribute values of basic types does not scale. Whether the attributes are values or symbols is up to the user, and whether later attributes accumulate or override earlier ones is also up to how the user interprets them. TemplatesIf a UDA is attached to a template declaration, then it will be automatically attached to all direct members of instances of that template. If any of those members are templates themselves, this rule applies recursively: @("foo") template Outer(T) { struct S { int x; } int y; void fun() {} @("bar") template Inner(U) { int z; } } pragma(msg, __traits(getAttributes, Outer!int.S)); // prints AliasSeq!("foo") pragma(msg, __traits(getAttributes, Outer!int.S.x)); // prints AliasSeq!() pragma(msg, __traits(getAttributes, Outer!int.y)); // prints AliasSeq!("foo") pragma(msg, __traits(getAttributes, Outer!int.fun)); // prints AliasSeq!("foo") pragma(msg, __traits(getAttributes, Outer!int.Inner)); // prints AliasSeq!("foo", "bar") pragma(msg, __traits(getAttributes, Outer!int.Inner!int.z)); // prints AliasSeq!("foo", "bar") UDAs cannot be attached to template parameters. Copyright © 1999-2026 by the D Language Foundation | Page generated by
Ddoc on Mon Nov 9 05:59:18 2026
| ||||||||||||||||||||||
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |