我有以下几点:
let mut my_number = 32.90;
如何打印my_number的类型?
使用type和type_of不起作用。有其他方法可以打印数字的类型吗?
我有以下几点:
let mut my_number = 32.90;
如何打印my_number的类型?
使用type和type_of不起作用。有其他方法可以打印数字的类型吗?
当前回答
我非常喜欢@Coautose之前的回答,但如果有人只想要没有名称空间的类型名称,例如C而不是a::b::C,这里是一个修改后的宏版本,看起来像预期的那样工作:
macro_rules! ty {
($type:ty) => {{
let result = std::any::type_name::<$type>();
match result.rsplit_once(':') {
Some((_, s)) => s,
None => result,
}
}};
}
用法:
debug!("Testing type name: {}", ty!(A));
其他回答
如果你只是想找出一个变量的类型,并愿意在编译时执行,你可能会导致一个错误,并让编译器拾取它。
例如,将变量设置为一个无效的类型:
let mut my_number: () = 32.90;
// let () = x; would work too
error[E0308]: mismatched types
--> src/main.rs:2:29
|
2 | let mut my_number: () = 32.90;
| ^^^^^ expected (), found floating-point number
|
= note: expected type `()`
found type `{float}`
或者调用无效的方法:
let mut my_number = 32.90;
my_number.what_is_this();
error[E0599]: no method named `what_is_this` found for type `{float}` in the current scope
--> src/main.rs:3:15
|
3 | my_number.what_is_this();
| ^^^^^^^^^^^^
或访问无效字段:
let mut my_number = 32.90;
my_number.what_is_this
error[E0610]: `{float}` is a primitive type and therefore doesn't have fields
--> src/main.rs:3:15
|
3 | my_number.what_is_this
| ^^^^^^^^^^^^
These reveal the type, which in this case is actually not fully resolved. It’s called “floating-point variable” in the first example, and “{float}” in all three examples; this is a partially resolved type which could end up f32 or f64, depending on how you use it. “{float}” is not a legal type name, it’s a placeholder meaning “I’m not completely sure what this is”, but it is a floating-point number. In the case of floating-point variables, if you don't constrain it, it will default to f64¹. (An unqualified integer literal will default to i32.)
参见:
编译器错误消息中的{integer}或{float}是什么?
¹可能仍然有一些让编译器困惑的方法,使它无法在f32和f64之间做出决定;我不确定。它曾经像32.90.eq(&32.90)一样简单,但现在两者都被视为f64,并且可以愉快地进行,所以我不知道。
我非常喜欢@Coautose之前的回答,但如果有人只想要没有名称空间的类型名称,例如C而不是a::b::C,这里是一个修改后的宏版本,看起来像预期的那样工作:
macro_rules! ty {
($type:ty) => {{
let result = std::any::type_name::<$type>();
match result.rsplit_once(':') {
Some((_, s)) => s,
None => result,
}
}};
}
用法:
debug!("Testing type name: {}", ty!(A));
有一个不稳定的函数std::intrinsic::type_name可以获取类型的名称,尽管您必须使用Rust的夜间构建(这在稳定的Rust中不太可能工作)。这里有一个例子:
#![feature(core_intrinsics)]
fn print_type_of<T>(_: &T) {
println!("{}", unsafe { std::intrinsics::type_name::<T>() });
}
fn main() {
print_type_of(&32.90); // prints "f64"
print_type_of(&vec![1, 2, 4]); // prints "std::vec::Vec<i32>"
print_type_of(&"foo"); // prints "&str"
}
更新,原始答案如下
trait函数type_name如何,它对于快速获取类型名称非常有用。
pub trait AnyExt {
fn type_name(&self) -> &'static str;
}
impl<T> AnyExt for T {
fn type_name(&self) -> &'static str {
std::any::type_name::<T>()
}
}
fn main(){
let my_number = 32.90;
println!("{}",my_number.type_name());
}
输出:
f64
原来的答案
我写了一个宏type_of!()来调试,它来自std dbg!()。
pub fn type_of2<T>(v: T) -> (&'static str, T) {
(std::any::type_name::<T>(), v)
}
#[macro_export]
macro_rules! type_of {
// NOTE: We cannot use `concat!` to make a static string as a format argument
// of `eprintln!` because `file!` could contain a `{` or
// `$val` expression could be a block (`{ .. }`), in which case the `eprintln!`
// will be malformed.
() => {
eprintln!("[{}:{}]", file!(), line!());
};
($val:expr $(,)?) => {
// Use of `match` here is intentional because it affects the lifetimes
// of temporaries - https://stackoverflow.com/a/48732525/1063961
match $val {
tmp => {
let (type_,tmp) = $crate::type_of2(tmp);
eprintln!("[{}:{}] {}: {}",
file!(), line!(), stringify!($val), type_);
tmp
}
}
};
($($val:expr),+ $(,)?) => {
($($crate::type_of!($val)),+,)
};
}
fn main(){
let my_number = type_of!(32.90);
type_of!(my_number);
}
输出:
[src/main.rs:32] 32.90: f64
[src/main.rs:33] my_number: f64
短篇小说;
fn tyof<T>(_: &T) -> String {
std::any::type_name::<T>().into()
}
很长的故事;
trait Type {
fn type_of(&self) -> String;
}
macro_rules! Type {
($($ty:ty),*) => {
$(
impl Type for $ty {
fn type_of(&self) -> String {
stringify!($ty).into()
}
}
)*
}
}
#[rustfmt::skip]
Type!(
u8, i8, u16, i16, u32, i32, i64, u64, i128, String, [()], (), Vec<()>, &u8, &i8, &u16, &i16, &u32, &i32, &i64, &u64, &i128, &str, &[()], &Vec<()>, &()
// add any struct, enum or type you want
);
macro_rules! tyof {
($var: expr) => {{
$var.type_of()
}};
}
fn main() {
let x = "Hello world!";
println!("{}", tyof!(x));
// or
println!("{}", x.type_of());
let x = 5;
println!("{}", tyof!(x));
// or
println!("{}", x.type_of());
}