D 1.0   D 2.0
About Japanese Translation

Last update Sun Feb 6 11:33:00 2011

宣言

Declaration:
        typedef Decl
        alias Decl
        Decl

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


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


BasicType2:
        *
        [ ]
        [ Expression ]
        [ Expression .. Expression ]
        [ Type ]
        delegate Parameters 
        function Parameters 

Declarator:
        BasicType2opt ( Declarator ) DeclaratorSuffixesopt
        BasicType2opt Identifier DeclaratorSuffixesopt

DeclaratorSuffixes:
        DeclaratorSuffix
        DeclaratorSuffix DeclaratorSuffixes

DeclaratorSuffix:
        [ ]
        [ Expression ]
        [ Type ]
        TemplateParameterListopt Parameters 

IdentifierList:
        Identifier
        Identifier . IdentifierList
        TemplateInstance
        TemplateInstance . IdentifierList

StorageClasses:
	StorageClass
	StorageClass StorageClasses

StorageClass:
        abstract
        auto
        const
        deprecated
        extern
        final
        scope
        static
        synchronized

Property:
	@ Identifier

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
        in
        inout
        lazy
        out
        ref
        scope
        shared

MemberFunctionAttributes:
	MemberFunctionAttribute
	MemberFunctionAttribute MemberFunctionAttributes

MemberFunctionAttribute:
	const
	immutable
	inout
	shared
	FunctionAttribute

DefaultInitializerExpression:
	AssignExpression


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 はchar[6]型

class C { ... }

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

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

型定義

typedef によって、「強い型」を導入できます。強い型とは、型システムによって、 関数オーバーロードやデバッガに対して、オリジナルの型と厳密に区別される型です。

typedef int myint;

void foo(int x) { . }
void foo(myint m) { . }

 .
myint b;
foo(b);	        // foo(myint) が呼ばれる
元の型とは違う初期値を typedef で指定することができます:
typedef int myint = 7;
myint m;        // 7 に初期化される

型の別名

型への別名を使うと便利なことがしばしばあります。 例えば、関数へのポインタのような長い複雑な型を記述するときなど。 Dでは、alias 宣言によってこれを実現します。

alias abc.Foo.bar myint;

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

alias int myint;

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

型のaliasは、Cのtypedefと同等です。

別名宣言

型だけでなく、任意のシンボルに対する 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型

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

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 が指すであろう型になることがあります。

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 初期化子は速度が最優先のコードを最適化する最後の手段としておくべきです。