如何约束运算符实现的右侧参数类型?
How to constrain type of right hand side parameter of operator implementation?
正在尝试实现通用 Vec
以实现 std::ops::Add
特性。我希望实现在加法时自动转换向量的基础类型,这样我就可以做这样的事情:
let u: Vec3<i32> = Vec3 { x: 1, y: 2, z: 3 };
let v: Vec3<i8> = Vec3 { x: 2, y: 3, z: 4 };
let w = u + v;
在呼叫站点不使用 .into()
。我已经实现了 From
特性(它会自动添加 Into
实现)并且它在一个简单的函数上运行良好:
fn foo<T: Into<Vec3<i32>>>(input: T) -> Vec3<i32> {
input.into()
}
let v: Vec3<i8> = Vec3 { x: 2, y: 3, z: 4 };
println!("{:?}", foo(v));
Link 到 非编译 示例 here。是否可以表达对运算符右侧参数类型的约束,如果可以,如何表达?
#![allow(dead_code)]
use std::convert::{From};
use std::ops::{Add};
#[derive(Debug)]
struct Vec3<T> {
x: T,
y: T,
z: T,
}
impl<T: Add<Output=T>> Add<U: Into<Vec3<i32>>> for Vec3<T> {
type Output = Vec3<T>;
fn add(self, rhs: U) -> Self::Output {
let rhs_converted: Vec3<T> = rhs.into();
Vec3 {
x: self.x.add(rhs_converted.x),
y: self.y.add(rhs_converted.y),
z: self.z.add(rhs_converted.z),
}
}
}
impl From<Vec3<i8>> for Vec3<i32> {
fn from(input: Vec3<i8>) -> Self {
Vec3 {
x: input.x.into(),
y: input.y.into(),
z: input.z.into(),
}
}
}
fn foo<T: Into<Vec3<i32>>>(input: T) -> Vec3<i32> {
input.into()
}
fn main() {
let u: Vec3<i32> = Vec3 { x: 1, y: 2, z: 3 };
let v: Vec3<i8> = Vec3 { x: 2, y: 3, z: 4 };
let w = u + v;
// println!("{:?}", foo(v));
println!("{:?}", w);
}
您需要在 Add
实施中将 U: Into<Vec3<i32>>
更改为 U: Into<Vec3<T>>
。此外,泛型 impl
中缺少类型参数 U
声明,它应该是 impl<T, U>
而不仅仅是 impl<T>
。在这些小修复之后,您的代码将按预期工作:
use std::convert::{From};
use std::ops::{Add};
#[derive(Debug)]
struct Vec3<T> {
x: T,
y: T,
z: T,
}
impl From<Vec3<i8>> for Vec3<i32> {
fn from(input: Vec3<i8>) -> Self {
Vec3 {
x: input.x.into(),
y: input.y.into(),
z: input.z.into(),
}
}
}
impl<T, U> Add<U> for Vec3<T>
where T: Add<Output=T>, U: Into<Vec3<T>>
{
type Output = Vec3<T>;
fn add(self, rhs: U) -> Self::Output {
let rhs_converted: Vec3<T> = rhs.into();
Vec3 {
x: self.x.add(rhs_converted.x),
y: self.y.add(rhs_converted.y),
z: self.z.add(rhs_converted.z),
}
}
}
fn main() {
let u: Vec3<i32> = Vec3 { x: 1, y: 2, z: 3 };
let v: Vec3<i8> = Vec3 { x: 2, y: 3, z: 4 };
let w = u + v;
println!("{:?}", w); // prints "Vec3 { x: 3, y: 5, z: 7 }" as expected
}
正在尝试实现通用 Vec
以实现 std::ops::Add
特性。我希望实现在加法时自动转换向量的基础类型,这样我就可以做这样的事情:
let u: Vec3<i32> = Vec3 { x: 1, y: 2, z: 3 };
let v: Vec3<i8> = Vec3 { x: 2, y: 3, z: 4 };
let w = u + v;
在呼叫站点不使用 .into()
。我已经实现了 From
特性(它会自动添加 Into
实现)并且它在一个简单的函数上运行良好:
fn foo<T: Into<Vec3<i32>>>(input: T) -> Vec3<i32> {
input.into()
}
let v: Vec3<i8> = Vec3 { x: 2, y: 3, z: 4 };
println!("{:?}", foo(v));
Link 到 非编译 示例 here。是否可以表达对运算符右侧参数类型的约束,如果可以,如何表达?
#![allow(dead_code)]
use std::convert::{From};
use std::ops::{Add};
#[derive(Debug)]
struct Vec3<T> {
x: T,
y: T,
z: T,
}
impl<T: Add<Output=T>> Add<U: Into<Vec3<i32>>> for Vec3<T> {
type Output = Vec3<T>;
fn add(self, rhs: U) -> Self::Output {
let rhs_converted: Vec3<T> = rhs.into();
Vec3 {
x: self.x.add(rhs_converted.x),
y: self.y.add(rhs_converted.y),
z: self.z.add(rhs_converted.z),
}
}
}
impl From<Vec3<i8>> for Vec3<i32> {
fn from(input: Vec3<i8>) -> Self {
Vec3 {
x: input.x.into(),
y: input.y.into(),
z: input.z.into(),
}
}
}
fn foo<T: Into<Vec3<i32>>>(input: T) -> Vec3<i32> {
input.into()
}
fn main() {
let u: Vec3<i32> = Vec3 { x: 1, y: 2, z: 3 };
let v: Vec3<i8> = Vec3 { x: 2, y: 3, z: 4 };
let w = u + v;
// println!("{:?}", foo(v));
println!("{:?}", w);
}
您需要在 Add
实施中将 U: Into<Vec3<i32>>
更改为 U: Into<Vec3<T>>
。此外,泛型 impl
中缺少类型参数 U
声明,它应该是 impl<T, U>
而不仅仅是 impl<T>
。在这些小修复之后,您的代码将按预期工作:
use std::convert::{From};
use std::ops::{Add};
#[derive(Debug)]
struct Vec3<T> {
x: T,
y: T,
z: T,
}
impl From<Vec3<i8>> for Vec3<i32> {
fn from(input: Vec3<i8>) -> Self {
Vec3 {
x: input.x.into(),
y: input.y.into(),
z: input.z.into(),
}
}
}
impl<T, U> Add<U> for Vec3<T>
where T: Add<Output=T>, U: Into<Vec3<T>>
{
type Output = Vec3<T>;
fn add(self, rhs: U) -> Self::Output {
let rhs_converted: Vec3<T> = rhs.into();
Vec3 {
x: self.x.add(rhs_converted.x),
y: self.y.add(rhs_converted.y),
z: self.z.add(rhs_converted.z),
}
}
}
fn main() {
let u: Vec3<i32> = Vec3 { x: 1, y: 2, z: 3 };
let v: Vec3<i8> = Vec3 { x: 2, y: 3, z: 4 };
let w = u + v;
println!("{:?}", w); // prints "Vec3 { x: 3, y: 5, z: 7 }" as expected
}