Suppose we have a function that takes generic parameters (not arguments)
const N: usize
const M: usize
is it possible to require constraints at COMPILE TIME of the form N >= M
or N, M are powers of 2
... ?
Suppose we have a function that takes generic parameters (not arguments)
const N: usize
const M: usize
is it possible to require constraints at COMPILE TIME of the form N >= M
or N, M are powers of 2
... ?
On stable, no. Using the type-level-booleans trick and the definitely-not-stable generic_const_expr
feature on nightly, yes:
#![feature(generic_const_exprs)]
trait True {}
struct Test<const B: bool>;
impl True for Test<true> {}
fn foo<const N: usize, const M: usize>()
where
Test<{N < M}>: True
{
}
fn main() {
foo::<4, 5>(); // Ok
foo::<5, 4>(); // Does not compile
}
For the powers of two you could just change your API to accept the base2 logarithm of the numbers (so 1
instead of 2
, 5
instead of 32
etc) — inside your code itself 2.pow(N)
will definitely get const-folded to its real value so there’s no runtime cost. Similarly instead of accepting N
and M
you can accept M
and the difference between the two values, so that invalid states aren’t representable (and again it will not have performance impact). But these solutions don’t always lead to the cleanest API.
There is a stable work-around:
Using unstable, I have seen this, which might be easier to use in some circumstances:
#![feature(generic_const_exprs)]
fn foo<const N: usize, const M: usize>()
where
[(); M-N-1]:,
{
}
fn main() {
foo::<4, 5>(); // Ok
foo::<5, 4>(); // Does not compile
}
Note this ensures M > N
. If you want M >= N
, omit the -1
.
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.