我有以下几点:

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,并且可以愉快地进行,所以我不知道。

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>"
}

这是在内部用来实现著名的{:?}格式化程序。

短篇小说;

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());
}

宏形式允许使用“无处不在”,而函数需要一个对象来解析。

宏表单(一行):

macro_rules! ty {($type:ty) => {std::any::type_name::<$type>()}}

形成的宏观形式:

macro_rules! ty {
    ($type:ty) => {
        std::any::type_name::<$type>()
    };
}

函数形式(借用是为了不破坏已解析的变量):

fn type_of<T>(_: &T) -> &'static str {std::any::type_name::<T>()}
fn type_of<T>(_: &T) -> &'static str {
    std::any::type_name::<T>()
}

例子:

macro_rules! ty {($type:ty) => {std::any::type_name::<$type>()}}
fn type_of<T>(_: &T) -> &'static str {std::any::type_name::<T>()}

struct DontMater<T>(T);

impl<T: std::fmt::Debug> std::fmt::Debug for DontMater<T> {
    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        fmt.write_fmt(format_args!("DontMater<{}>({:?})", ty!(T), self.0))
    }
}

fn main() {
    type µ = [Vec<String>; 7];
    println!("{:?}", DontMater(5_usize));
    println!("{:?}", DontMater("¤"));
    println!("{}", ty!(char));
    println!("{:?}", ty!(µ));
    println!("{}", type_of(&DontMater(72_i8)));
    println!("{:?}", type_of(&15_f64));
}

返回:

DontMater<usize>(5)
DontMater<&str>("¤")
char
"[alloc::vec::Vec<alloc::string::String>; 7]"
env_vars::DontMater<i8>
"f64"

这是@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游乐场的景观