0

I'm working on a library which will provide a trait for axis-aligned bounding boxes (AABB) operations. The trait is declared like this:

trait Aabb {
    type Precision : Zero + One + Num + PartialOrd + Copy;
    // [...]
}

I don't care which precision the user chooses, as long as these constraints are respected (though I don't really expect integer types to be chosen).

I'm having trouble using literals. Some operations require constant values, as an example:

let extension = 0.1;
aabb.extend(extension);

This doesn't work because Aabb::extend expects Aabb::Precision and not a float. My solution was something like this:

let mut ten = Aabb::Precision::zero();
for _ in 0..10 {
    ten = ten + Aabb::Precision::one();
}

aabb_extension = Aabb::Precision::one() / ten;

This works, but I need to resort to this every time I need a specific number and it is getting cumbersome. Is this really the only way?

3
  • You could require that Precision implements From<f64>. Commented Aug 19, 2016 at 6:51
  • @starblue I tried that too, but f32 doesn't implement From<f64> and that's the type I expect to be used the most Commented Aug 19, 2016 at 16:53
  • Well, you could use From<f32> then? Commented Aug 20, 2016 at 9:14

2 Answers 2

1

I need to resort to this every time I need a specific number and it is getting cumbersome. Is this really the only way?

Basically, yes. Unless you can answer the question of "how do you support converting a literal 0 to MyCustomTypeThatImplementsTheTrait".

You can't have it both ways — you can't ask for something to be generic and then use concrete literals.

You can have different workarounds. Providing base values like "zero" and "one", or having a "convert a specific type to yourself" method, for example.

You could also re-evaluate what you are attempting to do; perhaps you are thinking at too low a level. Indeed, what does it mean to "extend by 0.1" a type that represents points as floating point values between 0 and 1?

Maybe it would be better to have an expand_by_percentage method instead, or something else that makes sense in the domain.


See also:

Sign up to request clarification or add additional context in comments.

4 Comments

I extend by an arbitrary value because the algorithm requires AABBs with a minimum size, 0.1 is only bad if you are using something like 0.0001 to represent a meter. But then, you will run in a lot more issues than just an unoptimized tree. Anyway, thanks for you answer, I'll stick to manually building the values.
@LukeB. If you are allowing a generic type to be passed, then you can't make a blanket declaration about how the type implements the trait or what types of values will be well optimized by the type.
Can you give me an example of something that could go wrong? If you dont implement the trait correctly it is not going to work, but I cant really defend my code against that can I?
Unless you mean someone using something like i32 instead of f32? If so you are probably right, I haven't tested my code using integers yet so I don't know how it is going to react
1

In this case, I would recommend that you create your own trait and provide default implementations of the methods.

For example, I would naively imagine:

trait ApproximateValue: Zero + One {
    fn approximate(val: f64) -> ApproximateValue {
        // some algorithm to create "val" from Zero and One
    }
}

then, your Precision associated type will have a bound of ApproximateValue and you will just call Precision::approximate(0.1).

3 Comments

I can't compile that, it says missing associated type 'Output' value in the return of approximate, changing it to ApproximateValue<Output=ApproximateValue>>simply pushes the error forward.
@LukeB.: In the code I proposed there is no Output and ApproximateValue has no associated type... so I would need to see your code to understand what's going on (you can use the Rust playpen for example, or a gist).
I just copied and pasted your code (and added an unimplemented!() call). I tried just pasting your code in the playground but can't compile it there either, though the error is different the trait 'ApproximateValue' cannot be made into an object

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.