英文:
using rust newtype as generic type param
问题
I am trying to avoid specifying multiple traits on each use of generic type T. Can I use the newtype idiom to specify bounds once? This works but I'll have the where ... on each function.
fn prn<T>(arg: T)
where
    T: std::fmt::Debug + Copy,
{
    println!("{:?}", arg);
}
fn main() {
    let x: i32 = 1;
    prn(x);
}
Would it be possible to use a newtype like below to let me make fn prn generic and not have to specify all the traits on each impl?
pub struct MyData<T>(T)
where
    T: std::fmt::Debug + Copy + Clone + std::ops::Add<Output = T>;
My failed attempt below:
// WRONG - won't compile - is there syntax for newtype as type param?
fn prnt<MyData<T>>(arg: T) {
    println!("{:?}", arg);
}
fn main() {
    let x: i32 = 1;
    prnt(x);
}
英文:
I am trying to avoid specifying multiple traits on each use of generic type T.  Can I use the newtype idiom to specify bounds once?  This works but I'll have the where ... on each function.
fn prn<T>(arg: T)
where
    T: std::fmt::Debug + Copy,
{
    println!("{:?}", arg);
}
fn main() {
    let x: i32 = 1;
    prn(x);
}
Would it be possible to use a newtype like below to let me make fn prn generic and not have to specify all the traits on each impl?
pub struct MyData<T>(T)
where
    T: std::fmt::Debug + Copy + Clone + std::ops::Add<Output = T>;
My failed attempt below:
// WRONG - won't compile - is there syntax for newtype as type param?
fn prnt<MyData<T>>(arg: T) {
    println!("{:?}", arg);
}
fn main() {
    let x: i32 = 1;
    prnt(x);
}
答案1
得分: 2
不。newtype 是一种具体类型,不是任何类型的约束。
您可以使用特质继承和通用实现来"捆绑"特质:
trait Thing: std::fmt::Debug + Copy + Clone {}
impl<T> Thing for T where T: std::fmt::Debug + Copy + Clone {}
fn foo<T: Thing>(v: T) {
    println!("{v:?}");
}
fn main() {
    foo("bar");
    foo(1);
    foo(false);
}
虽然我认为您不能使用宏来声明通用约束(这将是一种替代方法),但如果您需要许多这样的特质,您可以使用宏一次性声明特质和通用实现:https://stackoverflow.com/a/57848887/8182118
英文:
> Would it be possible to use a newtype like below
No. A newtype is a concrete type, it's not any sort of constraint.
You can use trait inheritance and blanket implementations to "bundle" traits:
trait Thing: std::fmt::Debug + Copy + Clone {}
impl <T>Thing for T where T: std::fmt::Debug + Copy + Clone {}
fn foo<T: Thing>(v: T) {
    println!("{v:?}");
}
fn main() {
    foo("bar");
    foo(1);
    foo(false);
}
And while I don't think you can use macros to declare generic constraints (which would be an alternative) if you need many such traits you can use macros to declare the traits & blanket impls in one shot: https://stackoverflow.com/a/57848887/8182118
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论