Improve this page Github へのログインが必要です。 簡単な修正は、ここから fork、オンライン編集、pull request ができます。 大きな修正については、 通常の clone で行って下さい。 Page wiki 関連するWikiページを参照・編集 English このページの英語版(原文)

宣言

Declaration:
    AliasDeclaration
    AliasThisDeclaration
    Decl

AliasDeclaration:
    alias BasicType Declarator

AliasThisDeclaration:
    alias Identifier this

Decl:
    StorageClasses Decl
    BasicType Declarators ;
    BasicType Declarator FunctionBody
    AutoDeclaration

Declarators:
    DeclaratorInitializer
    DeclaratorInitializer , DeclaratorIdentifierList

DeclaratorInitializer:
    Declarator
    Declarator = Initializer

DeclaratorIdentifierList:
    DeclaratorIdentifier
    DeclaratorIdentifier , DeclaratorIdentifierList

DeclaratorIdentifier:
    Identifier
    Identifier = Initializer

BasicType:
    BasicTypeX
    .IdentifierList
    IdentifierList
    Typeof
    Typeof . IdentifierList
        const( Type )
        immutable( Type )
        shared( Type )
        inout( Type )


BasicTypeX:
    bool
    byte
    ubyte
    short
    ushort
    int
    uint
    long
    ulong
    char
    wchar
    dchar
    float
    double
    real
    ifloat
    idouble
    ireal
    cfloat
    cdouble
    creal
    void

BasicType2:
    *
    [ ]
    [ AssignExpression ]
    [ AssignExpression .. AssignExpression ]
    [ Type ]
    delegate Parameters FunctionAttributesopt
    function Parameters FunctionAttributesopt

Declarator:
    BasicType2opt ( Declarator ) DeclaratorSuffixesopt
    BasicType2opt Identifier DeclaratorSuffixesopt

DeclaratorSuffixes:
    DeclaratorSuffix
    DeclaratorSuffix DeclaratorSuffixes

DeclaratorSuffix:
    [ ]
    [ AssignExpression ]
    [ Type ]
    TemplateParameterListopt Parameters MemberFunctionAttributesopt Constraintopt

IdentifierList:
    Identifier
    Identifier . IdentifierList
    TemplateInstance
    TemplateInstance . IdentifierList

StorageClasses:
    StorageClass
    StorageClass StorageClasses

StorageClass:
    abstract
    auto
    const
    deprecated
    enum
    extern
    final
    immutable
    inout
    shared
    nothrow
    override
    pure
    __gshared
    Property
    scope
    static
    synchronized

Property:
    @ PropertyIdentifier

PropertyIdentifier:
    property
    safe
    trusted
    system
    disable


Type:
    BasicType
    BasicType Declarator2

Declarator2:
    BasicType2opt DeclaratorSuffixesopt
    BasicType2opt ( Declarator2 ) DeclaratorSuffixesopt

Parameters:
    ( ParameterList )
    ( )

ParameterList:
    Parameter
    Parameter , ParameterList
    ...

Parameter:
    InOutopt BasicType Declarator
    InOutopt BasicType Declarator ...
    InOutopt BasicType Declarator = DefaultInitializerExpression
    InOutopt Type
    InOutopt Type ...

InOut:
    InOutX
    InOut InOutX

InOutX:
    auto
    const
    final
    immutable
    in
    inout
    lazy
    out
    ref
    scope
   shared


FunctionAttributes:
    FunctionAttribute
    FunctionAttribute FunctionAttributes

FunctionAttribute:
    nothrow
    pure
    Property

MemberFunctionAttributes:
    MemberFunctionAttribute
    MemberFunctionAttribute MemberFunctionAttributes

MemberFunctionAttribute:
    const
    immutable
    inout
    shared
    FunctionAttribute


DefaultInitializerExpression:
    AssignExpression
    __FILE__
    __LINE__

Initializer:
    VoidInitializer
    NonVoidInitializer

NonVoidInitializer:
    AssignExpression
    ArrayInitializer
    StructInitializer

ArrayInitializer:
    [ ]
    [ ArrayMemberInitializations ]

ArrayMemberInitializations:
    ArrayMemberInitialization
    ArrayMemberInitialization ,
    ArrayMemberInitialization , ArrayMemberInitializations

ArrayMemberInitialization:
    NonVoidInitializer
    AssignExpression : NonVoidInitializer

StructInitializer:
    {  }
    { StructMemberInitializers }

StructMemberInitializers:
    StructMemberInitializer
    StructMemberInitializer ,
    StructMemberInitializer , StructMemberInitializers

StructMemberInitializer:
    NonVoidInitializer
    Identifier : NonVoidInitializer

宣言の構文

宣言の構文は、基本的に左から右へと読むことができます:

int x;    // x は int
int* x;   // x は int へのポインタ
int** x;  // x は int へのポインタ へのポインタ
int[] x;  // x は int の配列
int*[] x; // x は int へのポインタ の配列
int[]* x; // x は int の配列 へのポインタ

配列も、左から右へ読みます:

int[3] x;     // xは int の3要素配列
int[3][5] x;  // xは int の3要素配列 の5要素配列
int[3]*[5] x; // xは int の3要素配列 へのポインタ の5要素配列

関数へのポインタは function キーワードを使って宣言します:

int function(char) x; // x はcharを引数としてintを返す関数
                     // へのポインタ

int function(char)[] x; // x はcharを引数としてintを返す関数
                     // へのポインタ の配列


C風の宣言構文は非推奨となっています:

int x[3];          // x は int の3要素配列
int x[3][5];       // x は int の5要素配列 の3要素配列
int (*x[5])[3];    // x は int の3要素配列 へのポインタ の5要素配列
int (*x)(char);    // x はcharを引数としてintを返す関数
                   // へのポインタ
int (*[] x)(char); // x はcharを引数としてintを返す関数
                   // へのポインタ の配列

一行で複数のシンボルを宣言をする時は、 全ての変数が同じ型でなくてはなりません:

int x,y;   // x と y は int
int* x,y;  // x と y は intへのポインタ
int x,*y;  // エラー, 2種類の型
int[] x,y; // x と y は intの配列
int x[],y; // エラー, 2種類の型

暗黙の型推論

AutoDeclaration:
    StorageClasses AutoDeclarationX ;

AutoDeclarationX:
    Identifier = Initializer
    AutoDeclarationX , Identifier = Initializer

宣言が StorageClass で始まって、 型のわかる NonVoidInitializer が指定されているとき、 宣言の型は省略することが可能です。

static x = 3;      // x はint型
auto y = 4u;       // y はuint型
auto s = "string"; // s はimmutable(char)[]型

class C { ... }

auto c = new C();  // c はクラスCのインスタンスへのハンドル

NonVoidInitializer に前方参照を含むことはできません (この制限は将来的に取り除かれる予定です)。 暗黙に推論される型は、 実行時ではなくコンパイル時に静的に決まります。

ArrayLiteral の型は、 静的配列ではなく動的配列と推論されます:

auto v = ["hello", "world"]; // 型は string[]。 string[2] ではない

型の別名

AliasDeclaration は他の型の別名となるシンボルを作り、 その型の代わりとしてどんな場所でも使えるようにします。

alias abc.Foo.bar myint;

別名となっている型は、意味論的には元の型と全く同一に扱われます。 デバッガは二つの型を区別しませんし、関数オーバーロードの際も、 違いは生じません。例として:

alias int myint;

void foo(int x) { . }
void foo(myint m) { . } // ラー。同じ関数fooが二回以上定義されている

別名宣言

型だけでなく、任意のシンボルに対する alias を宣言できます。 例:

import string;

alias string.strlen mylen;
 ...
int len = mylen("hello"); // 実際には string.strlen() が呼ばれる

次のような別名宣言が全て有効です:

template Foo2(T) { alias T t; }
alias Foo2!(int) t1;
alias Foo2!(int).t t2;
alias t1.t t3;
alias t2 t4;

t1.t v1;  // v1 はint型
t2 v2;    // v2 はint型
t3 v3;    // v3 はint型
t4 v4;    // v4 はint型

シンボルの別名は、 長く修飾された名前を省略したり、 シンボルから別のシンボルへ転送する方法として役に立ちます:

version (Win32)
{
    alias win32.foo myfoo;
}
version (linux)
{
    alias linux.bar myfoo;
}

シンボルを現在のスコープへ ‘import’ するのに alias を利用できます:

alias string.strlen strlen;

alias によってオーバーロードされた関数達をまとめて ‘import’ することも可能で、 その際には、新しく導入される関数は、現在のスコープに存在した関数とさらにオーバーロードされます:

class A {
    int foo(int a) { return 1; }
}

class B : A {
    int foo( int a, uint b ) { return 2; }
}

class C : B {
    int foo( int a ) { return 3; }
    alias B.foo foo;
}

class D : C  {
}


void test()
{
    D b = new D();
    int i;

    i = b.foo(1, 2u);   // B.foo が呼ばれる
    i = b.foo(1);       // C.foo が呼ばれる
}

注: 型のaliasは、見かけだけではシンボルの alias 宣言と区別できないことがあります:

alias foo.bar abc; // 型? シンボル?

この区別は意味解析のフェーズで行われます。

aliasを式に対して使うことはできません:

struct S { static int i; }
S s;

alias s.i a; // 不正。s.i は式
alias S.i b; // ok
b = 4;       // S.i を 4 にする

extern 宣言

記憶域クラス extern つきで宣言された変数の領域は、 モジュール内には確保されません。 同じ名前で変数を定義した別のオブジェクトファイルを リンクする必要があります。 この機能の使いどころは、 C言語のグローバル変数宣言の利用です。

typeof

Typeof:
    typeof ( Expression )
   typeof ( return )

Typeof は、式の型に基づいて型を指定する方法です。 例えば:

void func(int i) {
 typeof(i) j;       // j の型はint
 typeof(3 + 6.0) x; // x の型はdouble
 typeof(1)* p;      // p の型はintへのポインタ
 int[typeof(p)] a;  // a の型はint[int*]

 writefln("%d", typeof('c').sizeof); // 1を表示
 double c = cast(typeof(1.0))j; // jをdoubleへキャスト
}

Expression は評価されず、 その型情報のみが生成されます:

void func() {
 int i = 1;
 typeof(++i) j; // j はintと宣言される。iは増加しない。
 writefln("%d", i);  // 1と表示
}

三つほど、特別な場合があります:

  1. typeof(this) は、例えメンバ関数の外であっても、 非静的メンバ関数の中で this が指すはずの型になることがあります。
  2. 同様に、typeof(super) は非静的メンバ関数の中で super が指すであろう型になることがあります。
  3. typeof(return) は、関数の中では、 その関数の返値の型になります。
class A { }

class B : A {
 typeof(this) x;  // x は B と宣言される
 typeof(super) y; // y は A と宣言される
}

struct C {
 typeof(this) z;  // z は C* と宣言される
 typeof(super) q; // エラー。構造体 C には super がない
}

typeof(this) r;   // エラー。構造体やクラス宣言の内部でない

Typeof がもっとも有効なのは、 templateを使ったジェネリックなコードを書く時です。

void 初期化子

VoidInitializer:
    void

通常、変数は明示的な Initializer で初期化されるか、 その型のデフォルトの値がセットされます。しかし Initializervoid であった場合に限り、 変数は初期化されません。そのような変数が 値をセットされる前に使用されると、未定義動作を引き起こすことがあります。

void foo() {
 int x = void;
 writefln(x);  // 意味のない値を表示
}

ですから、void 初期化子は速度が最優先のコードを最適化する最後の手段としておくべきです。

グローバル初期化子と静的初期化子

グローバル変数と静的変数の Initializer は、 コンパイル時評価が可能でなければなりません。 ポインタが他の関数やデータのアドレスで初期化できるかどうかは、 実装定義です。 実行時初期化は静的コンストラクタを使って行ってください。