我只是在学习Rust,希望编写使用泛型类型执行编译时算术的代码.

例如,在C++中,我可以编写以下代码(on Goldbolt):

#include <iostream>

template <int X>
struct Test {
    constexpr static int x = X;
};

template <int X1, int X2>
auto operator+(const Test<X1>&, const Test<X2>&) {
    return Test<X1 + X2>{};
}

int main() {
    const Test<4> a{};
    const Test<6> b{};
    const auto c = a + b;
    std::cout << c.x << '\n'; // prints 10
}

我试着用Rust(on Playground)编写类似的代码:

use std::ops::Add;

pub struct Test<const X: u8>;

impl<const X: u8> Test<X> {
    pub fn x(&self) -> u8 { X }
}

impl<const X1: u8, const X2: u8> Add<Test<X2>> for Test<X1> {
    type Output = Test<{X1 + X2}>;
    fn add(self, rhs: Test<X2>) -> Test<{X1 + X2}> {
        Test::<{X1 + X2}>{}
    }
}

fn main() {
    let a: Test<4> = Test{};
    let b: Test<6> = Test{};
    let c = a + b;
    println!("{}", c::x());
}

...但这不会被编译,因为generic parameters may not be used in const operations.这类事情对Rust 来说根本不可能,还是我可以try 另一种策略?

推荐答案

您可以这样做,但const个泛型尚未完成,因此它目前需要一个夜间编译器和一个显式启用的功能:

#![feature(generic_const_exprs)]
#![allow(incomplete_features)]

use std::ops::Add;

pub struct Test<const X: u8>;

impl<const X: u8> Test<X> {
    pub fn x(&self) -> u8 { X }
}

impl<const X1: u8, const X2: u8> Add<Test<X2>> for Test<X1> where [(); (X1 + X2) as usize]: {
    type Output = Test<{X1 + X2}>;
    fn add(self, _rhs: Test<X2>) -> Test<{X1 + X2}> {
        Test::<{X1 + X2}>{}
    }
}

fn main() {
    let a: Test<4> = Test{};
    let b: Test<6> = Test{};
    let c = a + b;
    let Test::<10> = c;
    println!("{}", c.x());
}

(Permalink to playground)

Rust相关问答推荐

如何容器化Linux上基于Rust的Windows应用程序的编译过程?

值为可变对象的不可变HashMap

限制未使用的泛型导致编译错误

获取与父字符串相关的&;str的原始片段

如何将实现多个特征的 struct 传递给接受这些特征为&;mut?

Tokio';s io::用Cursor拆分<;Vec<;u8>>;赢得';t get the full writted data

`actix-web` 使用提供的 `tokio` 运行时有何用途?

要求类型参数有特定的大小?

Boxing 如何将数据从堆栈移动到堆?

如何在Rust中使用Serde创建一个自定义的反序列化器来处理带有内部标记的枚举

如何在 Rust 中显式声明 std::str::Matches<'a, P> ?

Rust typestate 模式:实现多个状态?

是否可以通过可变引用推进可变切片?

按下 Ctrl + C 时优雅地停止命令并退出进程

在 Bevy 项目中为 TextureAtlas 精灵实施 NearestNeighbor 的正确方法是什么?

返回迭代器的特征

为什么我不能克隆可克隆构造函数的Vec?

为什么1..=100返回一个范围而不是一个整数?

只有一个字符被读入作为词法分析器的输入

BigUint 二进制补码