Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve error message for Quantity in unit slot #366

Merged
merged 2 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions au/code/au/quantity.hh
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,22 @@ class Quantity {
Rep value_{};
};

// Give more readable error messages when passing `Quantity` to a unit slot.
template <typename U, typename R>
struct AssociatedUnit<Quantity<U, R>> {
static_assert(
detail::AlwaysFalse<U, R>::value,
"Can't pass `Quantity` to a unit slot (see: "
"https://aurora-opensource.github.io/au/main/troubleshooting/#quantity-to-unit-slot)");
};
template <typename U, typename R>
struct AssociatedUnitForPoints<Quantity<U, R>> {
static_assert(
detail::AlwaysFalse<U, R>::value,
"Can't pass `Quantity` to a unit slot for points (see: "
"https://aurora-opensource.github.io/au/main/troubleshooting/#quantity-to-unit-slot)");
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Machinery to explicitly unblock integer division.
//
Expand Down
16 changes: 16 additions & 0 deletions au/code/au/quantity_point.hh
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,22 @@ struct QuantityPointMaker {
template <typename U>
struct AssociatedUnitForPoints<QuantityPointMaker<U>> : stdx::type_identity<U> {};

// Provide nicer error messages when users try passing a `QuantityPoint` to a unit slot.
template <typename U, typename R>
struct AssociatedUnit<QuantityPoint<U, R>> {
static_assert(
detail::AlwaysFalse<U, R>::value,
"Cannot pass QuantityPoint to a unit slot (see: "
"https://aurora-opensource.github.io/au/main/troubleshooting/#quantity-to-unit-slot)");
};
template <typename U, typename R>
struct AssociatedUnitForPoints<QuantityPoint<U, R>> {
static_assert(
detail::AlwaysFalse<U, R>::value,
"Cannot pass QuantityPoint to a unit slot (see: "
"https://aurora-opensource.github.io/au/main/troubleshooting/#quantity-to-unit-slot)");
};

// Type trait to detect whether two QuantityPoint types are equivalent.
//
// In this library, QuantityPoint types are "equivalent" exactly when they use the same Rep, and are
Expand Down
9 changes: 9 additions & 0 deletions au/error_examples.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

#include "au/au.hh"
#include "au/units/bytes.hh"
#include "au/units/feet.hh"
#include "au/units/hertz.hh"
#include "au/units/hours.hh"
Expand Down Expand Up @@ -69,6 +70,14 @@ void example_no_type_named_type_in_std_common_type() {
meters(1) + seconds(1);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// SECTION: Can't pass `Quantity` to a unit slot

void example_cant_pass_quantity_to_unit_slot() {
auto size = bytes(1234);
size = round_as<int>(bytes(10), size);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// SECTION: Integer division forbidden

Expand Down
10 changes: 10 additions & 0 deletions docs/discussion/idioms/unit-slots.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,16 @@ The reason we endorse the `QuantityMaker` overloads is because of the convention
a new `QuantityMaker` on the fly, then this benefit vanishes. (This is why unit expressions are
preferred for generic code.)

## What _doesn't_ fit in a unit slot?

A `Quantity`! It can certainly be tempting, as in some ways a `Quantity` can "feel like" a unit.
However, the `Quantity` also has a _runtime value_ attached. By contrast, unit slots can only take
things that have a single, unambiguous value, known _at compile time_.

Fortunately, if you make this mistake, you'll get a readable compiler error that directs you to [our
troubleshooting page](../../troubleshooting.md#quantity-to-unit-slot), so you can learn more about
why this isn't allowed, and what you can do to fix it.

## Summary

Many Au APIs have a "unit slot". These are designed for you to name the units explicitly at the
Expand Down
Loading
Loading