我有以下几点:
let mut my_number = 32.90;
如何打印my_number的类型?
使用type和type_of不起作用。有其他方法可以打印数字的类型吗?
我有以下几点:
let mut my_number = 32.90;
如何打印my_number的类型?
使用type和type_of不起作用。有其他方法可以打印数字的类型吗?
当前回答
更新,原始答案如下
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
其他回答
如果你事先知道所有的类型,你可以使用trait来添加type_of方法:
trait TypeInfo {
fn type_of(&self) -> &'static str;
}
impl TypeInfo for i32 {
fn type_of(&self) -> &'static str {
"i32"
}
}
impl TypeInfo for i64 {
fn type_of(&self) -> &'static str {
"i64"
}
}
//...
没有复杂或什么都没有,所以尽管有更多的限制,这是唯一的解决方案,让你得到一个字符串,是稳定的。(参见Boiethios的回答)然而,这是非常费力的,并且没有考虑类型参数,所以我们可以……
trait TypeInfo {
fn type_name() -> String;
fn type_of(&self) -> String;
}
macro_rules! impl_type_info {
($($name:ident$(<$($T:ident),+>)*),*) => {
$(impl_type_info_single!($name$(<$($T),*>)*);)*
};
}
macro_rules! mut_if {
($name:ident = $value:expr, $($any:expr)+) => (let mut $name = $value;);
($name:ident = $value:expr,) => (let $name = $value;);
}
macro_rules! impl_type_info_single {
($name:ident$(<$($T:ident),+>)*) => {
impl$(<$($T: TypeInfo),*>)* TypeInfo for $name$(<$($T),*>)* {
fn type_name() -> String {
mut_if!(res = String::from(stringify!($name)), $($($T)*)*);
$(
res.push('<');
$(
res.push_str(&$T::type_name());
res.push(',');
)*
res.pop();
res.push('>');
)*
res
}
fn type_of(&self) -> String {
$name$(::<$($T),*>)*::type_name()
}
}
}
}
impl<'a, T: TypeInfo + ?Sized> TypeInfo for &'a T {
fn type_name() -> String {
let mut res = String::from("&");
res.push_str(&T::type_name());
res
}
fn type_of(&self) -> String {
<&T>::type_name()
}
}
impl<'a, T: TypeInfo + ?Sized> TypeInfo for &'a mut T {
fn type_name() -> String {
let mut res = String::from("&mut ");
res.push_str(&T::type_name());
res
}
fn type_of(&self) -> String {
<&mut T>::type_name()
}
}
macro_rules! type_of {
($x:expr) => { (&$x).type_of() };
}
让我们使用它:
impl_type_info!(i32, i64, f32, f64, str, String, Vec<T>, Result<T,S>)
fn main() {
println!("{}", type_of!(1));
println!("{}", type_of!(&1));
println!("{}", type_of!(&&1));
println!("{}", type_of!(&mut 1));
println!("{}", type_of!(&&mut 1));
println!("{}", type_of!(&mut &1));
println!("{}", type_of!(1.0));
println!("{}", type_of!("abc"));
println!("{}", type_of!(&"abc"));
println!("{}", type_of!(String::from("abc")));
println!("{}", type_of!(vec![1,2,3]));
println!("{}", <Result<String,i64>>::type_name());
println!("{}", <&i32>::type_name());
println!("{}", <&str>::type_name());
}
输出:
i32
&i32
&&i32
&mut i32
&&mut i32
&mut &i32
f64
&str
&&str
String
Vec<i32>
Result<String,i64>
&i32
&str
生锈的操场
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>"
}
这是在内部用来实现著名的{:?}格式化程序。
你可以使用std::any::type_name函数。这并不需要一个夜间编译器或外部板条箱,结果是非常正确的:
fn print_type_of<T>(_: &T) {
println!("{}", std::any::type_name::<T>())
}
fn main() {
let s = "Hello";
let i = 42;
print_type_of(&s); // &str
print_type_of(&i); // i32
print_type_of(&main); // playground::main
print_type_of(&print_type_of::<i32>); // playground::print_type_of<i32>
print_type_of(&{ || "Hi!" }); // playground::main::{{closure}}
}
注意:如文档中所述,此信息只能用于调试目的:
这是用于诊断用途。字符串的确切内容和格式没有指定,只是尽力描述该类型。
如果你想让你的类型表示在不同的编译器版本中保持相同,你应该使用一个trait,就像phicr的答案一样。
其他一些答案不工作,但我发现typename crate工作。
Create a new project: cargo new test_typename Modify the Cargo.toml [dependencies] typename = "0.1.1" Modify your source code use typename::TypeName; fn main() { assert_eq!(String::type_name(), "std::string::String"); assert_eq!(Vec::<i32>::type_name(), "std::vec::Vec<i32>"); assert_eq!([0, 1, 2].type_name_of(), "[i32; 3]"); let a = 65u8; let b = b'A'; let c = 65; let d = 65i8; let e = 65i32; let f = 65u32; let arr = [1,2,3,4,5]; let first = arr[0]; println!("type of a 65u8 {} is {}", a, a.type_name_of()); println!("type of b b'A' {} is {}", b, b.type_name_of()); println!("type of c 65 {} is {}", c, c.type_name_of()); println!("type of d 65i8 {} is {}", d, d.type_name_of()); println!("type of e 65i32 {} is {}", e, e.type_name_of()); println!("type of f 65u32 {} is {}", f, f.type_name_of()); println!("type of arr {:?} is {}", arr, arr.type_name_of()); println!("type of first {} is {}", first, first.type_name_of()); }
输出结果为:
type of a 65u8 65 is u8
type of b b'A' 65 is u8
type of c 65 65 is i32
type of d 65i8 65 is i8
type of e 65i32 65 is i32
type of f 65u32 65 is u32
type of arr [1, 2, 3, 4, 5] is [i32; 5]
type of first 1 is i32
这是@Boiethios回答的简化版。我已经从原始解决方案中删除了一些“&”符号。
fn print_type_of<T>(_: T) {
println!("{}", std::any::type_name::<T>())
}
fn main() {
let s = "Hello";
let i = 42;
print_type_of(s); // &str
print_type_of(i); // i32
print_type_of(main); // playground::main
print_type_of(print_type_of::<i32>); // playground::print_type_of<i32>
print_type_of(|| "Hi!" ); // playground::main::{{closure}}
}
Rust游乐场的景观