enumにはCのunion的な使い方とCのenum的な使い方の両方があるということが分かったが、これを混ぜて使うことも多い。
// 色を表現する構造体 RGB #[derive(Copy,Clone,PartialEq)] struct RGB{ r:i32,g:i32,b:i32 } impl RGB{ fn New(R:i32,G:i32,B:i32)->RGB{return RGB{r:R,g:G,b:B};} } ////////////////////////////////////////////////// // 色を表現する構造体 HSV #[derive(Copy,Clone,PartialEq)] struct HSV{ h:f32,s:f32,v:f32 } impl HSV{ fn New(H:f32,S:f32,V:f32)->HSV{return HSV{h:H,s:S,v:V};} }
//////////////////////////////////////////////////
// 画像のピクセルを入れる型 // RGBの任意の値、HSVの任意の値 に加え、定数Invalid のどれかを入れることができる // Invalid(i32) と書き直すと少し理解がし易いが、入るのはInvalid一つだけなので意味的には違う // (概念的にはInvalidがたまたまi32にキャストできるだけで、i32を入れられるわけではないので) #[derive(Copy,Clone,PartialEq)] enum PixelInfo{ ColorRGB(RGB), // RGBを入れる場合 RGB型の変数ColorRGB ColorHSV(HSV), // HSVを入れる場合 HSV型の変数ColorHSV Invalid, // 定数を定義 RGBが無効のときはこれを入れておく事 }
////////////////////////////////////////////////// fn main() { let mut pixel:PixelInfo; // ピクセルを使うかどうかを決める let unuse:bool = false; if unuse { // 使わないときはInvalidを入れておく pixel = PixelInfo::Invalid; } else{ // 色を指定 pixel = PixelInfo::ColorRGB( RGB::New( 255, 0, 0, ) ); } if pixel == PixelInfo::Invalid{ // ピクセルが無効なら対応した処理を行う println!("the pixel is invalid"); } else if let PixelInfo::ColorHSV(c) = pixel{ // ピクセルが有効ならパターンマッチでcを定義して色を取得 println!("color HSV = ({} {} {})",c.h,c.s,c.v); } else if let PixelInfo::ColorRGB(c) = pixel{ // ピクセルが有効ならパターンマッチでcを定義して色を取得 println!("color RGB = ({} {} {})",c.r,c.g,c.b); } }
C++で似たようなコードを書くと、たぶん以下のようになる。
#include <iostream> struct RGB {int r, g, b;}; struct HSV {float h,s,v; }; union PixelInfo { RGB rgb; HSV hsv; // この定数も取れるようにする enum { INVALID, }Invalid; }; int main() { PixelInfo pi; pi.rgb = { 255, 255, 255 }; // 他の物を入れると無効になる pi.Invalid = PixelInfo::INVALID; std::cout << pi.Invalid; }