我有以下几点:
let mut my_number = 32.90;
如何打印my_number的类型?
使用type和type_of不起作用。有其他方法可以打印数字的类型吗?
我有以下几点:
let mut my_number = 32.90;
如何打印my_number的类型?
使用type和type_of不起作用。有其他方法可以打印数字的类型吗?
当前回答
最好使用这个:
fn print_type_of<T>(_: &T) -> String {
format!("{}", std::any::type_name::<T>())
}
fn main() {
let s = &"hello world".to_string();
let cloned_s = s.clone();
println!("{:?}", print_type_of(&s));
println!("{:?}", print_type_of(&cloned_s));
}
来自https://stackoverflow.com/a/29168659/6774636的推论
其他回答
如果你只是想找出一个变量的类型,并愿意在编译时执行,你可能会导致一个错误,并让编译器拾取它。
例如,将变量设置为一个无效的类型:
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,并且可以愉快地进行,所以我不知道。
更新,原始答案如下
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
UPD以下不再工作。检查Shubham的答案以作更正。
检查std::intrinsic::get_tydesc<T>()。它现在处于“实验”状态,但如果您只是对类型系统进行了修改,那么它是OK的。
请看下面的例子:
fn print_type_of<T>(_: &T) -> () {
let type_name =
unsafe {
(*std::intrinsics::get_tydesc::<T>()).name
};
println!("{}", type_name);
}
fn main() -> () {
let mut my_number = 32.90;
print_type_of(&my_number); // prints "f64"
print_type_of(&(vec!(1, 2, 4))); // prints "collections::vec::Vec<int>"
}
这是在内部用来实现著名的{:?}格式化程序。
您还可以使用println中的变量!("{:?}”,var)。如果没有为该类型实现Debug,则可以在编译器的错误消息中看到该类型:
mod some {
pub struct SomeType;
}
fn main() {
let unknown_var = some::SomeType;
println!("{:?}", unknown_var);
}
(游戏围栏)
虽然很脏,但很管用。
我非常喜欢@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));