Rust 为什么联合体上的模式匹配会有无法访问的模式警告?
鉴于这种情况,我无法理解联合体上的模式匹配为何不能正常工作:Rust 为什么联合体上的模式匹配会有无法访问的模式警告?,rust,pattern-matching,Rust,Pattern Matching,鉴于这种情况,我无法理解联合体上的模式匹配为何不能正常工作: 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"), } } 警告:无法访问的模式 -->src/main.r
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"),
}
}
警告:无法访问的模式
-->src/main.rs:12:13
|
12 | A{a2}=>println!(“浮动”),
| ^^^^^^^^
|
=注意:#[警告(无法访问的_模式)]默认打开
一个联合体的全部要点是编译器不会在联合体中存储任何关于它是什么类型的信息;这完全取决于程序员。因此,匹配
没有用于确定值类型的信息
因此,您的代码在概念上等同于
struct A {
a1: i32,
}
let b = A { a1: 42 };
match b {
A { a1 } => println!("int {}", a1),
A { a1 } => println!("float {}", a1),
}
在任何情况下都不会执行第二个匹配臂
事实上,在字段之间来回切换是联合的主要用法:
union A {
i: i32,
f: f32,
}
let a = A { i: 42 };
let b = unsafe { a.f };
println!("{}", b);
如果希望编译器跟踪您的变量,您可能希望使用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),
}
}
标记可以是您可以匹配的任何内容:
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),
}
}
我想你甚至可以在工会周围使用枚举
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),
}
}
谢谢你编辑我的问题!我不能改变工会。那么我可以使用std::any::TypeId
吗?当然可以,但是假设union有很多字段,那么你的建议就不太可行了!也许可以存储类型id
而不是is\u int
并与之匹配?@EhsanM.Kermani如果你有一个有100种可能性的联盟,你会遇到更大的问题。不管怎样,我还是会说静态地强制执行更多的东西会更好。如果这不是您的目标,那么Rust可能不适合您或您试图解决的问题。@EhsanM.Kermani另外,如果您有一个具有相同类型的两种可能性的联合体,那么TypeId
似乎将无法使用。