Skip to content

Support arithmetic and comparison operators on Constants when safe #607

@matthew-reynolds

Description

@matthew-reynolds

Currently, Constants do not support all arithmetic and comparison operations, as the goal is to ensure perfect representation.

Constants support the following mixins (All mixins below are commutative):

  • MakesQuantityFromNumber, which permits
    • Constant * raw num -> Quantity
    • Constant / raw num -> Quantity
  • ComposesWith, which permits
    • Constant * Constant -> Constant
    • Constant / Constant -> Constant
    • Constant * QuantityMaker -> QuantityMaker
    • Constant / QuantityMaker -> QuantityMaker
    • Constant * SingularNameFor -> SingularNameFor
    • Constant / SingularNameFor -> SingularNameFor
  • SupportsRationalPowers, which permits
    • au::pow<integer>(Constant) -> Constant
    • au::root<integer>(Constant) -> Constant
  • CanScaleByMagnitude, which permits
    • Constant * Magnitude -> Constant
    • Constant / Magnitude -> Constant

Plus implicit conversion to Quantity and therefore all the op(Constant, Quantity) -> op(Quantity, Quantity) operations supported on Quantities.

This leaves a few gaps when working purely in the Constant domain (Or, equivalently, in the Constant and Magnitude domain). See below:

Arithmetic Operators

Operator LHS Operand RHS Operand Status
+ (Unary) Constant N/A Prohibited but desired
- (Unary) Constant N/A Permitted
+ Constant Constant Prohibited but desired
- Constant Constant Prohibited but desired
* Constant Constant Permitted
/ Constant Constant Permitted
% Constant Constant Prohibited but desired
~ (Unary) Constant N/A Prohibited
& Constant Constant Prohibited
| Constant Constant Prohibited
^ Constant Constant Prohibited
<< Constant Constant Prohibited
>> Constant Constant Prohibited

Comparison Operators

Operator LHS Operand RHS Operand Status
== Constant Constant Prohibited but desired
!= Constant Constant Prohibited but desired
< Constant Constant Prohibited but desired
> Constant Constant Prohibited but desired
<= Constant Constant Prohibited but desired
>= Constant Constant Prohibited but desired
<=> Constant Constant Out of scope, C++20 only

For arithmetic operators, we need to be mindful about maintaining safety, particularly when working with prefixes, ScaledUnits, Pows, and RatioPows. We have previously talked about only supporting the subset of cases that are safe, which makes sense to me, though I can't recall what those unsafe cases actually are.

I think comparison operators will be more straightforward.

To summarize, I would like for there to be support for the following, from highest to lowest priority:

  • All comparison operators
  • Constant + Constant and Constant - Constant
    • This is a real point of friction for my team today. One common pattern we have is to have some Constant<Seconds> which we wish to subtract 1ms from. We are forced to convert to the Quantity domain (eg with CONST - milli(seconds)(1)) rather than staying in the Constant domain (eg with CONST - make_constant(milli(seconds) * mag<1>()))
  • Constant % Constant
    • This is probably a bit more controversial and less generally useful, but still seems like we ought to provide it if we can.
  • Unary +Constant
    • This is a no-op, but could be provided just for consistency and symmetry with the unary minus operator. As with floats and doubles, there is no integer promotion for the unary plus operator to apply, so the operand is just returned as is.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions