使用Rust的新类型作为通用类型参数

huangapple go评论52阅读模式
英文:

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&lt;T&gt;(arg: T)
where
    T: std::fmt::Debug + Copy,
{
    println!(&quot;{:?}&quot;, 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&lt;T&gt;(T)
where
    T: std::fmt::Debug + Copy + Clone + std::ops::Add&lt;Output = T&gt;;

My failed attempt below:

// WRONG - won&#39;t compile - is there syntax for newtype as type param?
fn prnt&lt;MyData&lt;T&gt;&gt;(arg: T) {
    println!(&quot;{:?}&quot;, 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 &lt;T&gt;Thing for T where T: std::fmt::Debug + Copy + Clone {}

fn foo&lt;T: Thing&gt;(v: T) {
    println!(&quot;{v:?}&quot;);
}
fn main() {
    foo(&quot;bar&quot;);
    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

huangapple
  • 本文由 发表于 2023年2月18日 20:41:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/75493410.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定