Reputation: 63
I know that I can use the TypeId
to find out if an arg is of some specific type:
use std::any::{Any, TypeId};
fn is_string<T: ?Sized + Any>(_s: &T) -> bool {
TypeId::of::<String>() == TypeId::of::<T>()
}
but is there a way to know that an arg is of some generic type, without caring about the inner type?
For exapmle, can I somehow find out if an arg is a Vec<_>, without caring for the inner type?
use std::any::{Any, TypeId};
fn is_vec<T: ?Sized + Any>(_s: &T) -> bool {
TypeId::of::<Vec<_>>() == TypeId::of::<T>() // This fails with error[E0282]: type annotations needed
}
I would like to know if this is possible in any way in Rust, not only using TypeId.
Upvotes: 0
Views: 620
Reputation: 2654
There is a generalizable way to do this in stable rust, although it won't let you check if a dyn Any
is a Vec<_>
. instead, what I did was create a super trait of any with an impl for both Vec<T>
and dyn Any
. Code:
trait MyAny:Any{
fn get_container(&self)->Container;
}
impl<T:Any> MyAny for Vec<T>{
fn get_container(&self)->Container{
Vector
}
}
impl MyAny for dyn Any{
fn get_container(&self)->Container{
Any
}
}
with container being an enum defined as
#[derive(Clone,Copy,PartialEq,Eq)]
#[non_exhaustive]
enum Container{
Vector,
Any,
}
from there, defining an is_vec
function is easy:
fn is_vec<T:MyAny + ?Sized>(s:&T)->bool{
s.get_container() == Vector
}
Upvotes: 1
Reputation: 35983
Right now, no way to do this in stable Rust comes to my mind.
However, as you ask for any way, here's a thing using specialization on nightly rust:
#![feature(specialization)]
trait TIsVector {
fn is_vector(&self) -> bool;
}
impl<T> TIsVector for T {
default fn is_vector(&self) -> bool {
false
}
}
impl<T> TIsVector for Vec<T> {
default fn is_vector(&self) -> bool {
true
}
}
fn main() {
dbg!(1usize.is_vector());
dbg!(true.is_vector());
dbg!("sdf".is_vector());
dbg!(vec![1,2,3].is_vector());
}
Upvotes: 0