is it possible with Rust to create a struct which contains one generic value but this is bound to specific types? In C++ I would use std::is_integral - cppreference.com and other stuff to create bounds that are checked at compile time and automated deduced.
The goal is to create function that could take the specified values and the use has not to specify the type.
Yes, a Rust struct can be generic, although it's more idiomatic to put the trait bounds on specific impl blocks rather than restricting the entire type unless that's needed for some technical reason. So you would write struct PropertyData<T> { value: T } and then specify where T: … in impl blocks only.
After some thinking and with the help/hints of you I was able to solve my problem so far. At least the first step. I use now following approach to begin with:
trait DataTypes {}
struct Data<T: DataTypes> {
value: T,
}
impl<T> Data<T>
where T: DataTypes
{
pub fn new(value: T) -> Self {
Self {
value
}
}
}
impl DataTypes for bool {}
impl DataTypes for i8 {}
impl DataTypes for u8 {}
impl DataTypes for String {}
impl DataTypes for Vec<u8> {}
fn main() {
let bool_data = Data::new(false);
let i8_data = Data::new(4i8);
let u8_data = Data::new(6u8);
let string_data = Data::new("Hallo".to_owned());
let vec_data = Data::new(vec![1, 2, 3, 4]);
}
Note that this doesn't obey the best practice I described above. The trait bound on both the struct declaration and the current impl block is superfluous – you could and should leave it off, so:
trait DataTypes {}
struct Data<T> {
value: T,
}
impl<T> Data<T> {
pub fn new(value: T) -> Self {
Self {
value
}
}
}
impl DataTypes for bool {}
impl DataTypes for i8 {}
impl DataTypes for u8 {}
impl DataTypes for String {}
impl DataTypes for Vec<u8> {}
fn main() {
let bool_data = Data::new(false);
let i8_data = Data::new(4i8);
let u8_data = Data::new(6u8);
let string_data = Data::new("Hallo".to_owned());
let vec_data = Data::new(vec![1, 2, 3, 4]);
}
You should only apply the T: DataTypes trait bound when it's actually needed. Also, don't call it DataTypes; call it DataType in singular. Naturally, traits can be implemented for more than one type (that's basically the whole point of abstracting over types!), so it's superfluous and non-idiomatic to call them by plurals.
This is what @H2CO3 meant. It's not necessary to add a bound on the Data struct. (I know it's unusual, but you usually omit the bound in the struct when possible.)
But there is no harm in being able to construct such a value! It might even save the day in generic/macro-heavy code. Unless it causes memory unsafety, you should not restrict construction. Restrict only the operations that actually need to use the trait's methods or rely on the trait being implemented for memory safety.