Ehs*_*ani 2 pattern-matching rust
鉴于文档,我无法理解为什么联合上的模式匹配不能正常工作:
union A {
a1: i32,
a2: f32,
}
struct B(A);
let b = B(A { a2: 1.0 });
unsafe {
match b.0 {
A { a1 } => println!("int"),
A { a2 } => println!("float"),
}
}
Run Code Online (Sandbox Code Playgroud)
warning: unreachable pattern
--> src/main.rs:12:13
|
12 | A { a2 } => println!("float"),
| ^^^^^^^^
|
= note: #[warn(unreachable_patterns)] on by default
Run Code Online (Sandbox Code Playgroud)
a的全部意义union在于编译器不会在union它的类型中存储任何信息; 这完全取决于程序员.因此,没有用于match确定值的类型的信息.
因此,您的代码在概念上等同于
struct A {
a1: i32,
}
let b = A { a1: 42 };
match b {
A { a1 } => println!("int {}", a1),
A { a1 } => println!("float {}", a1),
}
Run Code Online (Sandbox Code Playgroud)
在任何情况下都不会执行第二个匹配臂.
事实上,在字段之间来回切换是一个主要用途union:
union A {
i: i32,
f: f32,
}
let a = A { i: 42 };
let b = unsafe { a.f };
println!("{}", b);
Run Code Online (Sandbox Code Playgroud)
enum如果您希望编译器跟踪您拥有的变体,您可能希望使用.在某些情况下,枚举被称为标记联合,因为它正是它们的原样:带有标记的并集以识别联合包含的内容.
否则,您需要以其他方式跟踪联合中实际的类型.一种方法是实现自己的标记:
union A {
a1: i32,
a2: f32,
}
struct B {
is_int: bool,
data: A,
}
let b = B {
is_int: false,
data: A { a2: 1.0 },
};
unsafe {
match b {
B {
is_int: true,
data: A { a1 },
} => println!("int {}", a1),
B {
is_int: false,
data: A { a2 },
} => println!("float {}", a2),
}
}
Run Code Online (Sandbox Code Playgroud)
标签可以是您可以匹配的任何内容:
union A {
a1: i32,
a2: f32,
}
struct B {
kind: Kind,
data: A,
}
enum Kind {
Int,
Float,
}
let b = B {
kind: Kind::Float,
data: A { a2: 1.0 },
};
unsafe {
match b {
B {
kind: Kind::Int,
data: A { a1 },
} => println!("int {}", a1),
B {
kind: Kind::Float,
data: A { a2 },
} => println!("float {}", a2),
}
}
Run Code Online (Sandbox Code Playgroud)
我想你甚至可以用一个枚举各地工会...
union A {
a1: i32,
a2: f32,
}
enum B {
Int(A),
Float(A),
}
let b = B::Float(A { a2: 1.0 });
unsafe {
match b {
B::Int(A { a1 }) => println!("int {}", a1),
B::Float(A { a2 }) => println!("float {}", a2),
}
}
Run Code Online (Sandbox Code Playgroud)