等価演算子

通常のC++ではある型のポインタ同士の等価演算は純粋にアドレスの同値比較なのだが、
C++/CLIのハンドル同士の等価演算は少しばかり違うらしい。


こんなコードを書いてみる。

ref class CManagedHoge{
private:
	int n;
public:
	CManagedHoge() : n( 0 ) {
	}
	CManagedHoge( int value ) : n( value ) {
	}

	int getValue() {
		return n;
	}
};

bool operator == ( CManagedHoge% left, CManagedHoge% right ) {
	return left.getValue() == right.getValue();
}

bool operator == ( CManagedHoge^ left, CManagedHoge^ right ) {
	return left->getValue() == right->getValue();
}

class CNativeHoge {
private:
	int n;
public:
	CNativeHoge() : n( 0 ) {
	}
	CNativeHoge( int value ) : n( value ) {
	}
	
	int getValue() {
		return n;
	}
};

bool operator == ( CNativeHoge& left, CNativeHoge& right ) {
	return left.getValue() == right.getValue();
}

int main( array< String^ >^ args ) {
	{
		CManagedHoge^ hoge1 = gcnew CManagedHoge( 1 );
		CManagedHoge^ hoge2 = gcnew CManagedHoge( 2 );
		CManagedHoge^ hoge3 = gcnew CManagedHoge( 1 );

		Console::WriteLine( hoge1 == hoge2 );
		Console::WriteLine( hoge2 == hoge3 );
		Console::WriteLine( hoge1 == hoge3 );

		CManagedHoge hoge1_(1);
		CManagedHoge hoge2_(2);
		CManagedHoge hoge3_(1);

		Console::WriteLine( hoge1_ == hoge2_ );
		Console::WriteLine( hoge2_ == hoge3_ );
		Console::WriteLine( hoge1_ == hoge3_ );
	}

	{
		CNativeHoge* hoge1 = new CNativeHoge(1);
		CNativeHoge* hoge2 = new CNativeHoge(2);
		CNativeHoge* hoge3 = new CNativeHoge(1);

		Console::WriteLine( hoge1 == hoge2 );
		Console::WriteLine( hoge2 == hoge3 );
		Console::WriteLine( hoge1 == hoge3 );

		CNativeHoge hoge1_(1);
		CNativeHoge hoge2_(2);
		CNativeHoge hoge3_(1);

		Console::WriteLine( hoge1_ == hoge2_ );
		Console::WriteLine( hoge2_ == hoge3_ );
		Console::WriteLine( hoge1_ == hoge3_ );
	}

	return 0;
}

ご覧のとおり、C++/CLIではハンドル型同士の等価演算子が定義可能である(VC++2008EEで確認)。
さらにref classのハンドル型同士の等価演算子コンパイラに自動生成され、
Object::ReferenceEqualsが適用される。これがC++との大きな違いである。


まぁ、C#でハンドルに対するoperator == をoverrideできるのを考えれば当たり前といえば当たり前。


C++/CLIのハンドルを「C++のポインタみたいなもの」って説明してるのをたまに見るのだが、
こういうのがあると、そう簡単に言ってはいかんよなぁとか思うわけで。