I'm just learning Rust and would like to write code that uses generic types to perform compile-time arithmetic.
For example, in C I can write the following code (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
}
I try to write analogous code in 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());
}
...but this won't compile, since generic parameters may not be used in const operations
. Is this kind of thing simply impossible to do with Rust, or is there another strategy I can try?
CodePudding user response:
You can do it, but const
generics aren't complete yet, so it currently requires a nightly compiler and an explicitly enabled feature:
#![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());
}