我有以下内容:
let mut my_number = 32.90;
我该如何打印my_number
的类型?
使用type
和type_of
都无法实现。是否有其他方法可以打印出该数字的类型?
有一个@ChrisMorgan的回答介绍了如何在稳定版Rust中获取近似类型("float"),还有一个@ShubhamJain的回答介绍了如何通过不稳定的函数在夜版Rust中获取精确类型(“f64”)。
现在,以下是一种在稳定版Rust中获取精确类型(即在f32和f64之间进行选择)的方法:
fn main() {
let a = 5.;
let _: () = unsafe { std::mem::transmute(a) };
}
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> main.rs:3:27
|
3 | let _: () = unsafe { std::mem::transmute(a) };
| ^^^^^^^^^^^^^^^^^^^
|
= note: source type: `f64` (64 bits)
= note: target type: `()` (0 bits)
更新
涡轮鱼语法变体
fn main() {
let a = 5.;
unsafe { std::mem::transmute::<_, ()>(a) }
}
这是@Boiethios答案的简化版本。我从原始方案中删除了一些'&amp;'符号。
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}}
}
&
符号。但当类型实现了Copy
时(例如&str
,i32
和函数指针),这甚至会使差异更小。 - E net4有些其他的答案不可行,但我发现typename库可以使用。
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
typename
无法正常工作。使用问题中的 my_number
运行会出现以下错误:“无法在模糊的数字类型 {float}
上调用方法 type_name_of
。帮助:您必须为此绑定指定一个类型,例如 f32
”。 - Antony Hatchkins0.65
并且结果良好:c 的类型为 0.65 0.65 是 f64
。
这是我的版本:rustc 1.38.0-nightly (69656fa4c 2019-07-13)
。 - Flyqfn 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));
}
,推理如下:
短篇小说;
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"
#![feature(type_name_of_val)]
use std::any::type_name_of_val;
fn main() {
let mut my_number = 32.90;
println!("{}", type_name_of_val(&my_number));
}
a::b::C
变成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));
Pizza<topping::Pepperoni>
会打印出 Pepperoni>
。rsplit
! - MEMark