diff --git a/au/BUILD.bazel b/au/BUILD.bazel
index 27a89d48..1ee74f1f 100644
--- a/au/BUILD.bazel
+++ b/au/BUILD.bazel
@@ -25,7 +25,9 @@ cc_library(
deps = [
":chrono_interop",
":constant",
+ ":constants",
":math",
+ ":units",
],
)
diff --git a/docs/alternatives/index.md b/docs/alternatives/index.md
index 5badf78e..e82c0d81 100644
--- a/docs/alternatives/index.md
+++ b/docs/alternatives/index.md
@@ -908,15 +908,12 @@ features.
href="https://mpusz.github.io/mp-units/2.0/users_guide/framework_basics/faster_than_lightspeed_constants/">"Faster
than lightspeed" constants
-
+ |
- Constants as types
- Perfect conversion policy
- Implicit Quantity conversion
- -
- No built-in values yet (see #90)
-
+ - Includes exact constants from SI 2019
|
diff --git a/docs/howto/index.md b/docs/howto/index.md
index c3f07fbb..d8d4b046 100644
--- a/docs/howto/index.md
+++ b/docs/howto/index.md
@@ -6,6 +6,8 @@ using the library. Here's a summary of what you'll find.
- **[New units](./new-units.md).** How to add a new unit of measure that the library doesn't
include.
+- **[New constants](./new-constants.md).** How to add a custom physical constant.
+
- **[New dimensions](./new-dimensions.md).** How to add a new, independent base dimension.
- **[Inter-library Interoperation](./interop/index.md).** How to set up automatic correspondence
diff --git a/docs/howto/new-constants.md b/docs/howto/new-constants.md
new file mode 100644
index 00000000..d3060584
--- /dev/null
+++ b/docs/howto/new-constants.md
@@ -0,0 +1,83 @@
+# Defining new constants
+
+This page explains how to define new constants that aren't [included in the
+library](../reference/constant.md#built-in).
+
+!!! tip
+ If you think it _should_ be included in the library, feel free to [file an
+ issue](https://github.com/aurora-opensource/au/issues): there's no harm in asking.
+
+ In order for us to consider it, it should be relatively widely used. It also needs to have an
+ _exact_ value: we don't have a great way to deal with values that can change over time.
+
+ If these conditions don't apply, then follow the directions in this guide to define a _custom_
+ constant for your project.
+
+## Methods of definition
+
+There are two ways to define a new constant. The only difference is _whether you need a label_ for
+your constant. In either case, you create a constant by calling `make_constant(...)`. The argument
+is a [unit slot](../discussion/idioms/unit-slots.md), so you can pass it anything that goes into
+a unit slot.
+
+### Ad hoc (no special label)
+
+Pass any ad hoc unit expression to the unit slot. The constant will produce correct results in
+code, in every situation. It will even have _a_ label, which will identify it exactly. The label
+will simply be cumbersome.
+
+!!! example "Example: speed of light in an ad hoc manner"
+ Here's how to create a constant for the speed of light, without giving it a special symbol.
+
+ ```cpp
+ constexpr auto c = make_constant(meters / second * mag<299'792'458>());
+ ```
+
+ Here's an example use case, in user code:
+
+ ```cpp
+ std::cout << (0.8 * c) << std::endl;
+ ```
+
+ The above prints `"0.8 [299792458 m/s]"`. Notice how the unit label, `"[299792458 m/s]"`, is
+ _correct_, but _cumbersome_.
+
+### Full unit definition (includes custom label)
+
+First, follow a stripped down version of the [new unit instructions](./new-units.md) to define
+a _unit_ for the constant. The only thing you need to give it is a _label_; you can omit the
+instructions for quantity makers and so on.
+
+Next, pass an instance of this custom unit to `make_constant`.
+
+!!! example "Example: speed of light with full unit definition"
+ Here's how to create a constant for the speed of light using a full custom unit, with label.
+
+ === "C++14"
+ ```cpp
+ // In `.hh` file:
+ struct SpeedOfLightUnit : decltype(Meters{} / Seconds{} * mag<299'792'458>()) {
+ static constexpr const char label[] = "c";
+ };
+ constexpr auto c = make_constant(SpeedOfLightUnit{});
+
+ // In `.cc` file:
+ constexpr const char SpeedOfLightUnit::label[];
+ ```
+
+ === "C++17"
+ ```cpp
+ // In `.hh` file:
+ struct SpeedOfLightUnit : decltype(Meters{} / Seconds{} * mag<299'792'458>()) {
+ static constexpr inline const char label[] = "c";
+ };
+ constexpr auto c = make_constant(SpeedOfLightUnit{});
+ ```
+
+ Here's an example use case, in user code:
+
+ ```cpp
+ std::cout << (0.8 * c) << std::endl;
+ ```
+
+ The above prints `"0.8 c"`.
diff --git a/docs/install.md b/docs/install.md
index d14fe1ad..ccf5b453 100644
--- a/docs/install.md
+++ b/docs/install.md
@@ -120,7 +120,7 @@ to your `deps` attribute, and include the appropriate files.
| Dependency | Headers provided | Notes |
|------------|------------------|-------|
-| `@au//au` | `"au/au.hh"`
`"au/fwd.hh"`
`"au/units/*.hh"`
`"au/units/*_fwd.hh"` | Core library functionality. See [all available units](https://github.com/aurora-opensource/au/tree/main/au/units) |
+| `@au//au` | `"au/au.hh"`
`"au/fwd.hh"`
`"au/units/*.hh"`
`"au/units/*_fwd.hh"`
`"au/constants/*.hh"` | Core library functionality. See [all available units](https://github.com/aurora-opensource/au/tree/main/au/units) and [constants](./reference/constant.md#built-in) |
| `@au//au:io` | `"au/io.hh"` | `operator<<` support |
| `@au//au:testing` | `"au/testing.hh"` | Utilities for writing googletest tests
_Note:_ `testonly = True` |
@@ -141,7 +141,7 @@ In either case, here are the main targets and include files provided by the Au l
| Target | Headers provided | Notes |
|--------|------------------|-------|
-| `Au::au` | `"au/au.hh"`
`"au/fwd.hh"`
`"au/io.hh"`
`"au/units/*.hh"`
`"au/units/*_fwd.hh"` | Core library functionality. See [all available units](https://github.com/aurora-opensource/au/tree/main/au/units) |
+| `Au::au` | `"au/au.hh"`
`"au/fwd.hh"`
`"au/io.hh"`
`"au/units/*.hh"`
`"au/units/*_fwd.hh"`
`"au/constants/*.hh"` | Core library functionality. See [all available units](https://github.com/aurora-opensource/au/tree/main/au/units) |
| `Au::testing` | `"au/testing.hh"` | Utilities for writing googletest tests |
!!! note
@@ -336,7 +336,10 @@ Here's how:
creates a file, `~/au.hh`, which packages the entire library in a single file with these three
units.
- To see the full list of available units, search the `.hh` files in the `au/units/` folder. For
- example, `meters` will include the contents of `au/units/meters.hh`.
+ example, `meters` will include the contents of `"au/units/meters.hh"`.
+ - Similarly, to see the full list of available constants, search the `.hh` files in the
+ `au/constants/` folder. For example, `speed_of_light` will include the contents of
+ `"au/constants/speed_of_light.hh"`, which provides the constant `au::SPEED_OF_LIGHT`.
- Provide the `--noio` flag if you prefer to avoid the expense of the `` library.
Now you have a file, `~/au.hh`, which you can add to your `third_party` folder.
diff --git a/docs/reference/constant.md b/docs/reference/constant.md
index cc777e83..61b19b33 100644
--- a/docs/reference/constant.md
+++ b/docs/reference/constant.md
@@ -23,6 +23,45 @@ still store `5` under the hood.
This approach means that if subsequent operations cancel out the constant, this cancellation is both
_exact_ and has _zero runtime cost_.
+## Built-in constants included with Au {#built-in}
+
+Au includes a number of built-in constants. Each constant is in its own include file, in the folder
+`"au/constant"` --- for example, `"au/constant/speed_of_light.hh"`.
+
+The constant object itself is in the top-level `au::` namespace, and uses an UPPERCASE naming
+convention, as with all other constants in the library --- for example, `au::SPEED_OF_LIGHT`.
+
+We spell out the constant name in full to avoid ambiguity. However, this can be overly verbose. We
+encourage users to define their own copy of each constant, with a more usable name --- for example:
+
+```cpp
+constexpr auto c = au::SPEED_OF_LIGHT;
+```
+
+This "copy" is essentially free, because the constant is a [monovalue
+type](./detail/monovalue_types.md), and therefore empty.
+
+Here are the constants that we include with Au:
+
+| Name | Symbol | Value | Include (under `"au/constants/"`) | Object name (under `au::` namespace) |
+| ---- | ------ | ----- | ------- | ----------- |
+| Avogadro constant | $N_A$ | $6.022\,140\,76 \times 10^{23}\,\, \text{mol}^{-1}$ | `avogadro_constant.hh` | `AVOGADRO_CONSTANT` |
+| Boltzmann constant | $k_B$ | $1.380\,649 \times 10^{-23}\,\, \text{J} / \text{K}$ | `boltzmann_constant.hh` | `BOLTZMANN_CONSTANT` |
+| Cesium hyperfine transition frequency | $\Delta \nu_{Cs}$ | $9\,192\,631\,770\,\, \text{Hz}$ | `cesium_hyperfine_transition_frequency.hh` | `CESIUM_HYPERFINE_TRANSITION_FREQUENCY` |
+| Elementary charge | $e$ | $1.602\,176\,634 \times 10^{-19}\,\, \text{C}$ | `elementary_charge.hh` | `ELEMENTARY_CHARGE` |
+| Luminous efficacy of light at $540\,\, \text{THz}$ | $K_{cd}$ | $683\,\, \text{lm} / \text{W}$ | `luminous_efficacy_540_terahertz.hh` | `LUMINOUS_EFFICACY_540_TERAHERTZ` |
+| Planck constant | $h$ | $6.626\,070\,15 \times 10^{-34}\,\, \text{J} \cdot \text{s}$ | `planck_constant.hh` | `PLANCK_CONSTANT` |
+| Reduced Planck constant | $\hbar$ | $1.054\,571\,817 \times 10^{-34}\,\, \text{J} \cdot \text{s}$ | `reduced_planck_constant.hh` | `REDUCED_PLANCK_CONSTANT` |
+| Speed of light | $c$ | $299\,792\,458\,\, \text{m} / \text{s}$ | `speed_of_light.hh` | `SPEED_OF_LIGHT` |
+
+Our policy is to include only exactly defined constants with the library. This rules out many
+useful constants, such as the universal gravitational constant $G$, the _new_ (post-2019) permeability
+of free space $\mu_0$, and so on. For these, we can't reasonably provide values that will satisfy
+all users at all times. However, defining custom constants for your own project is straightforward,
+as we explain in the next section, and in our [how-to guide for custom
+constants](../howto/new-constants.md).
+
+
## Constructing `Constant`
`Constant` encodes all information about the value in its type. Moreover, it has only a single
diff --git a/docs/reference/detail/monovalue_types.md b/docs/reference/detail/monovalue_types.md
index 89c8fc02..32c297a7 100644
--- a/docs/reference/detail/monovalue_types.md
+++ b/docs/reference/detail/monovalue_types.md
@@ -37,6 +37,7 @@ Here are some canonical examples in Au.
| `Zero` | `ZERO` | Comparing to any `Quantity` |
| `Magnitude<>` | `ONE` | - Equality comparison with other Magnitudes
- `get_value(ONE)`
|
| `Radians` (and other units) | `Radians{}` (no special pre-formed instance) | Arithmetic with other units, such as `Radians{} / Meters{}` |
+| `Constant<...>` | `SPEED_OF_LIGHT` | - Comparing to any same-dimension `Quantity`
- `Quantity` construction with exact conversion policy
- zero-cost multiplying to change units/dimensions of numbers and `Quantity` instances
|
## Switching between types and values {#switching}