Force? Coerce? Just add a policy argument instead
What API should override conversion safety checks?
mp-units uses "force" as a word to denote this, despite the fact that "force" already has an unrelated meaning in the context of units libraries. Au uses "coerce" for this purpose, which avoids this confusion, but has problems of its own. For example, it's a blunt hammer: it turns of all safety checks, and the reader can only guess what specific problem the author was trying to circumvent.
The upcoming Au 0.5.0 release provides a new solution. Conversion functions can take a second argument, which is a conversion risk policy. We have conversion risk sets, such as:
OVERFLOW_RISKTRUNCATION_RISKALL_RISKS(equal toOVERFLOW_RISK | TRUNCATION_RISK)
To turn a risk set into a policy, pass it to ignore(), or check().
A key benefit is that it expresses the author's intent much more clearly and directly. Additionally, it only opts out of the specified risk(s).
To see this in action, try fixing the individual compiler errors in https://godbolt.org/z/M1YPEP9fT.
Thanks, @chiphogg, for sharing this interesting idea. I didn't think about this before. Maybe one conversion member function is enough indeed.
However, I see a few challenges here:
- Even without
OVERFLOW_RISKprovided we may end up with overflows in some scenarios. - Even without
TRUNCATION_RISK, we allow truncation of floating-point numbers.
I am not sure how to solve that.
Good questions. I used them as motivation to write some docs I had been meaning to write, for our upcoming release: Conversion Risks discussion; Truncation discussion. Each doc has a subsection that answers one of the questions.
Even without
OVERFLOW_RISKprovided we may end up with overflows in some scenarios.
Yep. The default policy doesn't mean there's no overflow risk; it means there's low overflow risk. This is how it must be, because if we prevented every conversion that could overflow, it would destroy the usability of the library. It would also reduce safety against overflow, because if users had to add the override for every single conversion, it would become just noise, and they would be unable to distinguish the risky from the mundane.
The Overall risk versus individual values section emphasizes that allowed versions can still be lossy for some input values, but that this can only happen in cases that the library judges to be low risk.
Even without
TRUNCATION_RISK, we allow truncation of floating-point numbers.
Here, I would say that we shouldn't properly call this "truncation", because floating point numbers are inexact. The Floating point types section makes this argument at a little more length.
Additionally, since I wrote this comment, I realized another benefit of the conversion risk policy parameters. They aren't part of the name of the function, so they can work with important functions where we have no control over the name --- that is, constructors.
There was one use case I was looking forward to cleaning up, but I was disappointed by how little the readability improved. Then I realized that it could be a lot better if we supported constructors. I added constructor support, and cleaned it some more to use constructors, and then it looked a lot better!