D言語のis表現


isキーワードには2つの用法があり、===として(==と!==オペレータは破棄された)を用いることができ、これはjava内の==に相当し、==はjava内のequalsと同義である.値タイプ(単純タイプ、構造を含む)の全等判断と等しい判断は同じであり、クラスオブジェクトの全等判断は判断対象ポインタであり、等しい判断はopEqualsを呼び出す.
テスト:

import std.stdio;

class Test{
	public:
	bool opEquals(Test other){
		return true;
	}
}

struct Foo{
	int a = 0;
}

void outputEquals(T1, T2)(T1 v1, T2 v2){
	if (v1 == v2){
		writefln("equal");
	}else{
		writefln("not equal");
	}
}

void outputIs(T1, T2)(T1 v1, T2 v2){
	if (v1 is v2){
		writefln("is");
	}else{
		writefln("is not");
	}
}

void main(){
	auto a = new Test;
	auto b = new Test;
	Foo fooa;
	Foo foob;
	outputEquals(1, 1);
	outputIs(1, 1);
	outputEquals(a, b);
	outputIs(a, b);
	outputEquals(fooa, foob);
	outputIs(fooa, foob);
	foob.a = 1;
	outputEquals(fooa, foob);
	outputIs(fooa, foob);
}

isのもう一つの使い方はis式で、コンパイル期間中に実行され、主にタイプ判断に使用されます.コンパイル期間の値が等しい判断は==オペレータで,もちろんこれらの値が単純な値タイプであることが要求される.is式はタイプ抽出に便利であり,C++で一つのタイプが一つの関数であるか否かを判断することは困難であり,Dではisで判断すればよい.
詳細:
http://www.digitalmars.com/d/expression.html#IsExpression
DMD 0.174においてtype traitsが実装され、ここでReturnTypeは、以下のように実装される.

template ReturnType(alias dg)
{
    alias ReturnType!(typeof(dg)) ReturnType;
}

template ReturnType(dg)
{
    static if (is(dg R == return))
	alias R ReturnType;
    else
	static assert(0, "argument has no return type");
}

この2つのテンプレートは、前のテンプレートからタイプを抽出し、後のテンプレートからタイプを抽出する順序でなければなりません.
このis(dg R==return))は、dgというタイプが関数タイプ、関数ポインタタイプ、または委任タイプであるかどうかを判断し、これらのタイプが一致すると、戻り値タイプをRに割り当て、そうでないとRは定義されていないように見えます.