スポンサーリンク

Rustのenumについて学んだ話(1) unionとしての使い方

Rustのenumには三つの使い方がある。

まずはC言語におけるunionに近い使い方。

以下ではC_Union_Like型を定義しているが、この変数はi32,f32,Stringの「いずれか一つ」を代入することができる。

// Rust の enum は、C言語のunionに近い使い方ができる。
// 以下ではivalue,fvalue,svalueの三つのバリアントを定義しているが、
// 一度に有効なのは一つだけ。
enum C_Union_Like{
  ivalue(i32),
  fvalue(f32),
  svalue(String),
}
      
      
fn main() {

  // C_Union_Likeのivalueにi32を入れる。
  let mut cu:C_Union_Like = C_Union_Like::ivalue(33);

  // fvalueに入れたので、cuはf32を持つようになった
  cu = C_Union_Like::fvalue(7.5);

  // svalueに入れたので、cuはStringを持つようになった
  cu = C_Union_Like::svalue("hello".to_string());


  // cuは三つのバリアントを持つが、一度に有効なのは一つだけ。
  // cu がどの値を持っているかを知る方法は
  // パターンマッチングでマッチするかで判断する

  // cu が ivalue にマッチするなら、iiを定義し、ivalueの値を代入
  if let C_Union_Like::ivalue(ii)=cu {
    println!("int is used. {}",ii);
  }
  else if let C_Union_Like::fvalue(ff)=cu{
    println!("float is used. {}",ff);
  }
  else if let C_Union_Like::svalue(ss)=cu{
    println!("String is used. {}",ss);    
  }

}

このプログラムは、C/C++における以下に近い。

struct C_Union_Like {

    int type;
    union {
        int ivalue;
        float fvalue;
        //std::string svalue; // これはC++ではできないが、Rustならできる
    };
};


int main()
{

    C_Union_Like cu;

    cu.type = 0;
    cu.ivalue = 33;

    cu.type = 1;
    cu.fvalue = 7.5f;

    switch (cu.type) {
    case 0:
        printf("int is used. %d \n", cu.ivalue);
        break;
    case 1:
        printf("float is used. %d \n", cu.fvalue);
        break;
    }

}

Rustのenumは、C/C++のunionと違ってStringなどの複雑な型を取ることができる。さらに型情報も自動で持つので、unionのように自分で管理する必要がない。注意点として、今何が入っているかはパターンマッチングで判断する。上ではif letを使っているが、matchを使ってもよい。

fn main() {

  // C_Union_Likeのivalueにi32を入れる。
  let mut cu:C_Union_Like = C_Union_Like::ivalue(33);

  // svalueに入れたので、cuはStringを持つようになった
  cu = C_Union_Like::svalue("hello".to_string());

  // fvalueに入れたので、cuはf32を持つようになった
  cu = C_Union_Like::fvalue(7.5);



  // cuは三つのバリアントを持つが、一度に有効なのは一つだけ。
  // cu がどの値を持っているかを知る方法は
  // パターンマッチングでマッチするかで判断する

  // cuの取りうるバリアントが多い場合はmatchのほうが読みやすい
  match cu{
    C_Union_Like::ivalue(ii) => {
      println!("int is used. {}",ii);
    },
    C_Union_Like::fvalue(ff) => {
      println!("float is used. {}",ff);
    },
    C_Union_Like::svalue(ss) => {
      println!("String is used. {}",ss);
    },
    _ =>{}
  }

}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: