Skip to content

Commit

Permalink
Let u in unit_label(u) be a unit slot (#206)
Browse files Browse the repository at this point in the history
I just noticed this wasn't already the case, and this seemed silly and"
annoying.

I also added a missing test case for the mechanism that makes unit slots
work, namely, `AssociatedUnitT`.

And I updated the docs.
  • Loading branch information
chiphogg authored Dec 11, 2023
1 parent 013c343 commit 59ad95f
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 1 deletion.
2 changes: 1 addition & 1 deletion au/unit_of_measure.hh
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@ constexpr

template <typename Unit>
constexpr const auto &unit_label(Unit) {
return detail::as_char_array(UnitLabel<Unit>::value);
return detail::as_char_array(UnitLabel<AssociatedUnitT<Unit>>::value);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
12 changes: 12 additions & 0 deletions au/unit_of_measure_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ struct InvalidWrongMagType {
using Mag = char;
};

// Useful for testing "unit slot" compatibility in APIs.
template <typename UnitT>
struct SomeUnitWrapper {};
template <typename UnitT>
struct AssociatedUnit<SomeUnitWrapper<UnitT>> : stdx::type_identity<UnitT> {};

struct UnlabeledUnit : decltype(Feet{} * mag<9>()) {};

MATCHER_P(QuantityEquivalentToUnit, target, "") {
Expand Down Expand Up @@ -218,6 +224,10 @@ TEST(AssociatedUnitT, IsIdentityForTypeWithNoAssociatedUnit) {
StaticAssertTypeEq<AssociatedUnitT<double>, double>();
}

TEST(AssociatedUnitT, HandlesWrappersWhichHaveSpecializedAssociatedUnit) {
StaticAssertTypeEq<AssociatedUnitT<SomeUnitWrapper<Feet>>, Feet>();
}

TEST(UnitInverseT, CommutesWithProduct) {
StaticAssertTypeEq<UnitInverseT<UnitProductT<Feet, Minutes>>,
UnitProductT<UnitInverseT<Feet>, UnitInverseT<Minutes>>>();
Expand Down Expand Up @@ -598,6 +608,8 @@ TEST(UnitLabel, CommonPointUnitLabelWorksWithUnitProduct) {
AnyOf(StrEq("COM_PT[m / min, in / min]"), StrEq("COM_PT[in / min, m / min]")));
}

TEST(UnitLabel, APICompatibleWithUnitSlots) { EXPECT_THAT(unit_label(feet), StrEq("ft")); }

namespace detail {

TEST(Origin, ZeroForUnitWithNoSpecifiedOrigin) {
Expand Down
4 changes: 4 additions & 0 deletions docs/reference/unit.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ For a unit type `U`, or instance `u`, we can access the label as follows:
- `unit_label<U>()`
- `unit_label(u)`

Note that the `u` in `unit_label(u)` is a [unit slot](../discussion/idioms/unit-slots.md), so you
can pass anything that "acts like a unit" to it. For instance, you can say `unit_label(meters)`;
you don't need to write `unit_label(Meters{})`.

This function returns a reference to the array, which again is a compile time constant.

Note especially that the type is an _array_ (`[]`). A pointer (`*`) is _not_ acceptable. This is
Expand Down

0 comments on commit 59ad95f

Please sign in to comment.