forked from mpusz/mp-units
Prefixed units support redesigned
This commit is contained in:
@@ -121,6 +121,7 @@ NOTE: This library as of now compiles correctly only with gcc-9.1 and newer.
|
|||||||
- Added unit symbols definitions to `base_dimension` and `derived_unit`
|
- Added unit symbols definitions to `base_dimension` and `derived_unit`
|
||||||
- Added `coherent_derived_unit` helper
|
- Added `coherent_derived_unit` helper
|
||||||
- Added support for `operator<<` on `quantity`
|
- Added support for `operator<<` on `quantity`
|
||||||
|
- Refactored the way prefixed units are defined
|
||||||
|
|
||||||
- 0.3.1 Sep 18, 2019
|
- 0.3.1 Sep 18, 2019
|
||||||
- cmcstl2 dependency changed to range-v3 0.9.1
|
- cmcstl2 dependency changed to range-v3 0.9.1
|
||||||
|
161
doc/DESIGN.md
161
doc/DESIGN.md
@@ -157,7 +157,7 @@ helper:
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
template<typename Child, Exponent... Es>
|
template<typename Child, Exponent... Es>
|
||||||
struct derived_dimension;
|
struct derived_dimension : downcast_helper<Child, typename detail::make_dimension<Es...>::type> {};
|
||||||
```
|
```
|
||||||
|
|
||||||
`Child` class template parameter is a part of a CRTP idiom and is used to provide a downcasting facility
|
`Child` class template parameter is a part of a CRTP idiom and is used to provide a downcasting facility
|
||||||
@@ -229,68 +229,6 @@ struct unit : downcast_base<unit<D, R>> {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
Coherent derived units (units with `ratio<1>`) are created with a `coherent_derived_unit` helper:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
template<typename Child, fixed_string Symbol, Dimension D, typename Prefix = no_prefix>
|
|
||||||
struct coherent_derived_unit;
|
|
||||||
```
|
|
||||||
|
|
||||||
The above type exposes public `symbol` and `prefix` member types used to print unit symbol names.
|
|
||||||
|
|
||||||
For example to define the base unit of `length`:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
struct metre : coherent_derived_unit<metre, "m", length, si_prefix> {};
|
|
||||||
```
|
|
||||||
|
|
||||||
Again, similarly to `derived_dimension`, the first class template parameter is a CRTP idiom used
|
|
||||||
to provide downcasting facility (described below).
|
|
||||||
|
|
||||||
All other units are created with a `derived_unit` helper:
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
template<typename Child, fixed_string Symbol, typename...>
|
|
||||||
struct derived_unit;
|
|
||||||
```
|
|
||||||
|
|
||||||
The above type exposes public `symbol` member type used to print unit symbol names.
|
|
||||||
|
|
||||||
`derived_unit` has a few useful partial specializations:
|
|
||||||
- helper to create non-coherent units for a specified dimension
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
template<typename Child, fixed_string Symbol, Dimension D, Ratio R>
|
|
||||||
struct derived_unit<Child, Symbol, D, R>;
|
|
||||||
```
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
struct yard : derived_unit<yard, "yd", length, ratio<9'144, 10'000>> {};
|
|
||||||
```
|
|
||||||
|
|
||||||
- helper to create a named unit with a SI prefix
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
template<typename Child, fixed_string Symbol, Unit U>
|
|
||||||
struct derived_unit<Child, Symbol, U>;
|
|
||||||
```
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
struct kilometre : derived_unit<kilometre, "km", kilo<metre>> {};
|
|
||||||
```
|
|
||||||
|
|
||||||
- helper that automatically calculates ratio based on info in desired dimension and provided list
|
|
||||||
of units of base dimensions
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
template<typename Child, fixed_string Symbol, Dimension D, Unit U, Unit... Us>
|
|
||||||
struct derived_unit<Child, Symbol, D, U, Us...>;
|
|
||||||
```
|
|
||||||
|
|
||||||
```cpp
|
|
||||||
struct kilometre_per_hour : derived_unit<kilometre_per_hour, "km/h", velocity, kilometre, hour> {};
|
|
||||||
```
|
|
||||||
|
|
||||||
`units::Unit` is a concept that is satisfied by a type that is empty and publicly
|
`units::Unit` is a concept that is satisfied by a type that is empty and publicly
|
||||||
derived from `units::unit` class template:
|
derived from `units::unit` class template:
|
||||||
|
|
||||||
@@ -301,6 +239,96 @@ concept Unit =
|
|||||||
detail::is_unit<downcast_base_t<T>>; // exposition only
|
detail::is_unit<downcast_base_t<T>>; // exposition only
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Coherent derived units (units with `ratio<1>`) are created with a `coherent_derived_unit` class
|
||||||
|
template:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<typename Child, fixed_string Symbol, Dimension D, typename PrefixType = no_prefix>
|
||||||
|
struct coherent_derived_unit : downcast_helper<Child, unit<D, ratio<1>>> {
|
||||||
|
static constexpr auto symbol = Symbol;
|
||||||
|
using prefix_type = PrefixType;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
The above exposes public `prefix_type` member type and `symbol` used to print unit symbol
|
||||||
|
names. `prefix_type` is a tag type used to identify the type of prefixes to be used (i.e. SI,
|
||||||
|
data).
|
||||||
|
|
||||||
|
For example to define the coherent unit of `length`:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct metre : coherent_derived_unit<metre, "m", length, si_prefix> {};
|
||||||
|
```
|
||||||
|
|
||||||
|
Again, similarly to `derived_dimension`, the first class template parameter is a CRTP idiom used
|
||||||
|
to provide downcasting facility (described below).
|
||||||
|
|
||||||
|
To create the rest of derived units the following class template can be used:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<typename Child, basic_fixed_string Symbol, Dimension D, Ratio R>
|
||||||
|
struct derived_unit : downcast_helper<Child, unit<D, R>> {
|
||||||
|
static constexpr auto symbol = Symbol;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
User has to provide a symbol name, dimension, and a ratio relative to a coherent derived unit.
|
||||||
|
For example to define `minute`:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct minute : derived_unit<minute, "min", time, ratio<60>> {};
|
||||||
|
```
|
||||||
|
|
||||||
|
The `mp-units` library provides also a few helper class templates to simplify the above process.
|
||||||
|
|
||||||
|
For example to create a prefixed unit the following may be used:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<typename Child, Prefix P, Unit U>
|
||||||
|
requires requires { U::symbol; } && std::same_as<typename U::prefix_type, typename P::prefix_type>
|
||||||
|
struct prefixed_derived_unit : downcast_helper<Child, unit<typename U::dimension,
|
||||||
|
ratio_multiply<typename P::ratio,
|
||||||
|
typename U::ratio>>> {
|
||||||
|
static constexpr auto symbol = P::symbol + U::symbol;
|
||||||
|
using prefix_type = P::prefix_type;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
where `Prefix` is a concept requiring the instantiation of the following class template:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<typename PrefixType, Ratio R, basic_fixed_string Symbol>
|
||||||
|
struct prefix {
|
||||||
|
using prefix_type = PrefixType;
|
||||||
|
using ratio = R;
|
||||||
|
static constexpr auto symbol = Symbol;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
With this to create prefixed units user does not have to specify numeric value of the prefix ratio
|
||||||
|
or its symbol and just has to do the following:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct kilometre : prefixed_derived_unit<kilometre, kilo, metre> {};
|
||||||
|
```
|
||||||
|
|
||||||
|
For the cases where determining the exact ratio is not trivial another helper can be used:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
template<typename Child, basic_fixed_string Symbol, Dimension D, Unit U, Unit... Us>
|
||||||
|
struct deduced_derived_unit : downcast_helper<Child, detail::make_derived_unit<D, U, Us...>> {
|
||||||
|
static constexpr auto symbol = Symbol;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
This will deduce the ratio based on the ingredient units and their relation defined in the
|
||||||
|
dimension:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct mile_per_hour : deduced_derived_unit<mile_per_hour, "mi/h", velocity, mile, hour> {};
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### `Quantities`
|
### `Quantities`
|
||||||
|
|
||||||
`units::quantity` is a class template that expresses the quantity/amount of a specific dimension
|
`units::quantity` is a class template that expresses the quantity/amount of a specific dimension
|
||||||
@@ -416,6 +444,13 @@ of checks:
|
|||||||
3. If a quantity has an unknown dimension, the symbols of base dimensions will be used to construct
|
3. If a quantity has an unknown dimension, the symbols of base dimensions will be used to construct
|
||||||
a unit symbol (i.e. `2 m/kg^2`). In this case no prefix symbols are added.
|
a unit symbol (i.e. `2 m/kg^2`). In this case no prefix symbols are added.
|
||||||
|
|
||||||
|
#### Text Formatting
|
||||||
|
|
||||||
|
| Specifier | Replacement |
|
||||||
|
|-----------|--------------------------------------------------------------|
|
||||||
|
| `%q` | The quantity’s unit symbol |
|
||||||
|
| `%Q` | The quantity’s numeric value (as if extracted via `.count()` |
|
||||||
|
|
||||||
|
|
||||||
## Strong types instead of aliases, and type downcasting facility
|
## Strong types instead of aliases, and type downcasting facility
|
||||||
|
|
||||||
|
@@ -35,7 +35,7 @@ namespace units {
|
|||||||
data_[i] = txt[i];
|
data_[i] = txt[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr bool size() const noexcept { return N; }
|
[[nodiscard]] constexpr std::size_t size() const noexcept { return N; }
|
||||||
[[nodiscard]] constexpr const CharT* c_str() const noexcept { return data_; }
|
[[nodiscard]] constexpr const CharT* c_str() const noexcept { return data_; }
|
||||||
|
|
||||||
// auto operator==(const basic_fixed_string &) = default;
|
// auto operator==(const basic_fixed_string &) = default;
|
||||||
@@ -75,6 +75,20 @@ namespace units {
|
|||||||
{
|
{
|
||||||
return os << txt.c_str();
|
return os << txt.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<std::size_t N2>
|
||||||
|
[[nodiscard]] constexpr friend basic_fixed_string<CharT, N + N2> operator+(const basic_fixed_string& lhs, const basic_fixed_string<CharT, N2>& rhs) noexcept
|
||||||
|
{
|
||||||
|
CharT txt[lhs.size() + rhs.size() + 1] = {};
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
for(; i != lhs.size(); ++i)
|
||||||
|
txt[i] = lhs.c_str()[i];
|
||||||
|
for(size_t j = 0; j != rhs.size(); ++j)
|
||||||
|
txt[i + j] = rhs.c_str()[j];
|
||||||
|
|
||||||
|
return basic_fixed_string<CharT, N + N2>(txt);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename CharT, std::size_t N>
|
template<typename CharT, std::size_t N>
|
||||||
@@ -83,25 +97,4 @@ namespace units {
|
|||||||
template<std::size_t N>
|
template<std::size_t N>
|
||||||
using fixed_string = basic_fixed_string<char, N>;
|
using fixed_string = basic_fixed_string<char, N>;
|
||||||
|
|
||||||
// TODO gcc:92101
|
|
||||||
// hacked version to work with derived_unit
|
|
||||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92101
|
|
||||||
|
|
||||||
template<typename CharT, CharT... Chars>
|
|
||||||
struct basic_fixed_string_hack {
|
|
||||||
static constexpr CharT txt[] = { Chars..., '\0' };
|
|
||||||
|
|
||||||
static constexpr const CharT* c_str() noexcept
|
|
||||||
{
|
|
||||||
return txt;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
inline namespace hacks {
|
|
||||||
|
|
||||||
template<typename T, T... chars>
|
|
||||||
constexpr basic_fixed_string_hack<T, chars...> operator""_fs() { return {}; }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -31,7 +31,7 @@ namespace units {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept Acceleration = QuantityOf<T, acceleration>;
|
concept Acceleration = QuantityOf<T, acceleration>;
|
||||||
|
|
||||||
struct metre_per_second_sq : coherent_derived_unit<metre_per_second_sq, decltype("m/s^2"_fs), acceleration> {};
|
struct metre_per_second_sq : coherent_derived_unit<metre_per_second_sq, "m/s^2", acceleration> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -31,11 +31,11 @@ namespace units {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept Area = QuantityOf<T, area>;
|
concept Area = QuantityOf<T, area>;
|
||||||
|
|
||||||
struct square_metre : coherent_derived_unit<square_metre, decltype("m^2"_fs), area> {};
|
struct square_metre : coherent_derived_unit<square_metre, "m^2", area> {};
|
||||||
struct square_millimetre : derived_unit<square_millimetre, decltype("mm^2"_fs), area, millimetre> {};
|
struct square_millimetre : deduced_derived_unit<square_millimetre, "mm^2", area, millimetre> {};
|
||||||
struct square_centimetre : derived_unit<square_centimetre, decltype("cm^2"_fs), area, centimetre> {};
|
struct square_centimetre : deduced_derived_unit<square_centimetre, "cm^2", area, centimetre> {};
|
||||||
struct square_kilometre : derived_unit<square_kilometre, decltype("km^2"_fs), area, kilometre> {};
|
struct square_kilometre : deduced_derived_unit<square_kilometre, "km^2", area, kilometre> {};
|
||||||
struct square_foot : derived_unit<square_foot, decltype("ft^2"_fs), area, foot> {};
|
struct square_foot : deduced_derived_unit<square_foot, "ft^2", area, foot> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/base_dimensions.h>
|
#include <units/dimensions/si_base_dimensions.h>
|
||||||
#include <units/dimensions/electric_charge.h>
|
#include <units/dimensions/electric_charge.h>
|
||||||
#include <units/dimensions/voltage.h>
|
#include <units/dimensions/voltage.h>
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ namespace units {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept Capacitance = QuantityOf<T, capacitance>;
|
concept Capacitance = QuantityOf<T, capacitance>;
|
||||||
|
|
||||||
struct farad : coherent_derived_unit<farad, decltype("F"_fs), capacitance, si_prefix> {};
|
struct farad : coherent_derived_unit<farad, "F", capacitance, si_prefix> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/base_dimensions.h>
|
#include <units/dimensions/si_base_dimensions.h>
|
||||||
#include <units/quantity.h>
|
#include <units/quantity.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
@@ -32,7 +32,7 @@ namespace units {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept Current = QuantityOf<T, current>;
|
concept Current = QuantityOf<T, current>;
|
||||||
|
|
||||||
struct ampere : coherent_derived_unit<ampere, decltype("A"_fs), current, si_prefix> {};
|
struct ampere : coherent_derived_unit<ampere, "A", current, si_prefix> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/base_dimensions.h>
|
#include <units/dimensions/si_base_dimensions.h>
|
||||||
#include <units/dimensions/time.h>
|
#include <units/dimensions/time.h>
|
||||||
#include <units/dimensions/current.h>
|
#include <units/dimensions/current.h>
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ namespace units {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept ElectricCharge = QuantityOf<T, electric_charge>;
|
concept ElectricCharge = QuantityOf<T, electric_charge>;
|
||||||
|
|
||||||
struct coulomb : coherent_derived_unit<coulomb, decltype("C"_fs), electric_charge, si_prefix> {};
|
struct coulomb : coherent_derived_unit<coulomb, "C", electric_charge, si_prefix> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -22,7 +22,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/base_dimensions.h>
|
#include <units/dimensions/si_base_dimensions.h>
|
||||||
|
#include <units/dimensions/si_prefixes.h>
|
||||||
#include <units/dimensions/force.h>
|
#include <units/dimensions/force.h>
|
||||||
#include <units/dimensions/pressure.h>
|
#include <units/dimensions/pressure.h>
|
||||||
|
|
||||||
@@ -33,11 +34,11 @@ namespace units {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept Energy = QuantityOf<T, energy>;
|
concept Energy = QuantityOf<T, energy>;
|
||||||
|
|
||||||
struct joule : coherent_derived_unit<joule, decltype("J"_fs), energy, si_prefix> {};
|
struct joule : coherent_derived_unit<joule, "J", energy, si_prefix> {};
|
||||||
struct millijoule : derived_unit<millijoule, decltype("mJ"_fs), milli<joule>> {};
|
struct millijoule : prefixed_derived_unit<millijoule, milli, joule> {};
|
||||||
struct kilojoule : derived_unit<kilojoule, decltype("kJ"_fs), kilo<joule>> {};
|
struct kilojoule : prefixed_derived_unit<kilojoule, kilo, joule> {};
|
||||||
struct megajoule : derived_unit<megajoule, decltype("MJ"_fs), mega<joule>> {};
|
struct megajoule : prefixed_derived_unit<megajoule, mega, joule> {};
|
||||||
struct gigajoule : derived_unit<gigajoule, decltype("GJ"_fs), giga<joule>> {};
|
struct gigajoule : prefixed_derived_unit<gigajoule, giga, joule> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/base_dimensions.h>
|
#include <units/dimensions/si_base_dimensions.h>
|
||||||
#include <units/dimensions/mass.h>
|
#include <units/dimensions/mass.h>
|
||||||
#include <units/dimensions/acceleration.h>
|
#include <units/dimensions/acceleration.h>
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ namespace units {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept Force = QuantityOf<T, force>;
|
concept Force = QuantityOf<T, force>;
|
||||||
|
|
||||||
struct newton : coherent_derived_unit<newton, decltype("N"_fs), force, si_prefix> {};
|
struct newton : coherent_derived_unit<newton, "N", force, si_prefix> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -22,7 +22,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/base_dimensions.h>
|
#include <units/dimensions/si_base_dimensions.h>
|
||||||
|
#include <units/dimensions/si_prefixes.h>
|
||||||
#include <units/dimensions/time.h>
|
#include <units/dimensions/time.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
@@ -32,12 +33,12 @@ namespace units {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept Frequency = QuantityOf<T, frequency>;
|
concept Frequency = QuantityOf<T, frequency>;
|
||||||
|
|
||||||
struct hertz : coherent_derived_unit<hertz, decltype("Hz"_fs), frequency, si_prefix> {};
|
struct hertz : coherent_derived_unit<hertz, "Hz", frequency, si_prefix> {};
|
||||||
struct millihertz : derived_unit<millihertz, decltype("mHz"_fs), milli<hertz>> {};
|
struct millihertz : prefixed_derived_unit<millihertz, milli, hertz> {};
|
||||||
struct kilohertz : derived_unit<kilohertz, decltype("kHz"_fs), kilo<hertz>> {};
|
struct kilohertz : prefixed_derived_unit<kilohertz, kilo, hertz> {};
|
||||||
struct megahertz : derived_unit<megahertz, decltype("MHz"_fs), mega<hertz>> {};
|
struct megahertz : prefixed_derived_unit<megahertz, mega, hertz> {};
|
||||||
struct gigahertz : derived_unit<gigahertz, decltype("GHz"_fs), giga<hertz>> {};
|
struct gigahertz : prefixed_derived_unit<gigahertz, giga, hertz> {};
|
||||||
struct terahertz : derived_unit<terahertz, decltype("THz"_fs), tera<hertz>> {};
|
struct terahertz : prefixed_derived_unit<terahertz, tera, hertz> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -22,7 +22,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/base_dimensions.h>
|
#include <units/dimensions/si_base_dimensions.h>
|
||||||
|
#include <units/dimensions/si_prefixes.h>
|
||||||
#include <units/quantity.h>
|
#include <units/quantity.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
@@ -33,10 +34,10 @@ namespace units {
|
|||||||
concept Length = QuantityOf<T, length>;
|
concept Length = QuantityOf<T, length>;
|
||||||
|
|
||||||
// SI units
|
// SI units
|
||||||
struct metre : coherent_derived_unit<metre, decltype("m"_fs), length, si_prefix> {};
|
struct metre : coherent_derived_unit<metre, "m", length, si_prefix> {};
|
||||||
struct millimetre : derived_unit<millimetre, decltype("mm"_fs), milli<metre>> {};
|
struct millimetre : prefixed_derived_unit<millimetre, milli, metre> {};
|
||||||
struct centimetre : derived_unit<centimetre, decltype("cm"_fs), centi<metre>> {};
|
struct centimetre : prefixed_derived_unit<centimetre, centi, metre> {};
|
||||||
struct kilometre : derived_unit<kilometre, decltype("km"_fs), kilo<metre>> {};
|
struct kilometre : prefixed_derived_unit<kilometre, kilo, metre> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
@@ -59,10 +60,10 @@ namespace units {
|
|||||||
} // namespace literals
|
} // namespace literals
|
||||||
|
|
||||||
// US customary units
|
// US customary units
|
||||||
struct yard : derived_unit<yard, decltype("yd"_fs), length, ratio<9'144, 10'000>> {};
|
struct yard : derived_unit<yard, "yd", length, ratio<9'144, 10'000>> {};
|
||||||
struct foot : derived_unit<foot, decltype("ft"_fs), length, ratio_multiply<ratio<1, 3>, yard::ratio>> {};
|
struct foot : derived_unit<foot, "ft", length, ratio_multiply<ratio<1, 3>, yard::ratio>> {};
|
||||||
struct inch : derived_unit<inch, decltype("in"_fs), length, ratio_multiply<ratio<1, 12>, foot::ratio>> {};
|
struct inch : derived_unit<inch, "in", length, ratio_multiply<ratio<1, 12>, foot::ratio>> {};
|
||||||
struct mile : derived_unit<mile, decltype("mi"_fs), length, ratio_multiply<ratio<1'760>, yard::ratio>> {};
|
struct mile : derived_unit<mile, "mi", length, ratio_multiply<ratio<1'760>, yard::ratio>> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/base_dimensions.h>
|
#include <units/dimensions/si_base_dimensions.h>
|
||||||
#include <units/quantity.h>
|
#include <units/quantity.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
@@ -32,7 +32,7 @@ namespace units {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept LuminousIntensity = QuantityOf<T, luminous_intensity>;
|
concept LuminousIntensity = QuantityOf<T, luminous_intensity>;
|
||||||
|
|
||||||
struct candela : coherent_derived_unit<candela, decltype("cd"_fs), luminous_intensity, si_prefix> {};
|
struct candela : coherent_derived_unit<candela, "cd", luminous_intensity, si_prefix> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/base_dimensions.h>
|
#include <units/dimensions/si_base_dimensions.h>
|
||||||
#include <units/quantity.h>
|
#include <units/quantity.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
@@ -32,8 +32,8 @@ namespace units {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept Mass = QuantityOf<T, mass>;
|
concept Mass = QuantityOf<T, mass>;
|
||||||
|
|
||||||
struct kilogram : coherent_derived_unit<kilogram, decltype("kg"_fs), mass> {};
|
struct kilogram : coherent_derived_unit<kilogram, "kg", mass> {};
|
||||||
struct gram : derived_unit<gram, decltype("g"_fs), mass, ratio<1, 1000>> {};
|
struct gram : derived_unit<gram, "g", mass, ratio<1, 1000>> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -22,7 +22,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/base_dimensions.h>
|
#include <units/dimensions/si_base_dimensions.h>
|
||||||
|
#include <units/dimensions/si_prefixes.h>
|
||||||
#include <units/dimensions/energy.h>
|
#include <units/dimensions/energy.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
@@ -32,11 +33,11 @@ namespace units {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept Power = QuantityOf<T, power>;
|
concept Power = QuantityOf<T, power>;
|
||||||
|
|
||||||
struct watt : coherent_derived_unit<watt, decltype("W"_fs), power, si_prefix> {};
|
struct watt : coherent_derived_unit<watt, "W", power, si_prefix> {};
|
||||||
struct milliwatt : derived_unit<milliwatt, decltype("mW"_fs), milli<watt>> {};
|
struct milliwatt : prefixed_derived_unit<milliwatt, milli, watt> {};
|
||||||
struct kilowatt : derived_unit<kilowatt, decltype("kW"_fs), kilo<watt>> {};
|
struct kilowatt : prefixed_derived_unit<kilowatt, kilo, watt> {};
|
||||||
struct megawatt : derived_unit<megawatt, decltype("MW"_fs), mega<watt>> {};
|
struct megawatt : prefixed_derived_unit<megawatt, mega, watt> {};
|
||||||
struct gigawatt : derived_unit<gigawatt, decltype("GW"_fs), giga<watt>> {};
|
struct gigawatt : prefixed_derived_unit<gigawatt, giga, watt> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/base_dimensions.h>
|
#include <units/dimensions/si_base_dimensions.h>
|
||||||
#include <units/dimensions/force.h>
|
#include <units/dimensions/force.h>
|
||||||
#include <units/dimensions/area.h>
|
#include <units/dimensions/area.h>
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ namespace units {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept Pressure = QuantityOf<T, pressure>;
|
concept Pressure = QuantityOf<T, pressure>;
|
||||||
|
|
||||||
struct pascal : coherent_derived_unit<pascal, decltype("Pa"_fs), pressure, si_prefix> {};
|
struct pascal : coherent_derived_unit<pascal, "Pa", pressure, si_prefix> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -29,30 +29,31 @@ namespace units {
|
|||||||
|
|
||||||
// prefix tags
|
// prefix tags
|
||||||
struct si_prefix;
|
struct si_prefix;
|
||||||
|
|
||||||
// SI prefixes
|
// SI prefixes
|
||||||
|
|
||||||
template<Unit U> using atto = unit<typename U::dimension, ratio_multiply<typename U::ratio, ratio<1, std::atto::den>>>;
|
using atto = prefix<si_prefix, ratio<1, std::atto::den>, "a">;
|
||||||
template<Unit U> using femto = unit<typename U::dimension, ratio_multiply<typename U::ratio, ratio<1, std::femto::den>>>;
|
using femto = prefix<si_prefix, ratio<1, std::femto::den>, "f">;
|
||||||
template<Unit U> using pico = unit<typename U::dimension, ratio_multiply<typename U::ratio, ratio<1, std::pico::den>>>;
|
using pico = prefix<si_prefix, ratio<1, std::pico::den>, "p">;
|
||||||
template<Unit U> using nano = unit<typename U::dimension, ratio_multiply<typename U::ratio, ratio<1, std::nano::den>>>;
|
using nano = prefix<si_prefix, ratio<1, std::nano::den>, "n">;
|
||||||
template<Unit U> using micro = unit<typename U::dimension, ratio_multiply<typename U::ratio, ratio<1, std::micro::den>>>;
|
using micro = prefix<si_prefix, ratio<1, std::micro::den>, "µ">;
|
||||||
template<Unit U> using milli = unit<typename U::dimension, ratio_multiply<typename U::ratio, ratio<1, std::milli::den>>>;
|
using milli = prefix<si_prefix, ratio<1, std::milli::den>, "m">;
|
||||||
template<Unit U> using centi = unit<typename U::dimension, ratio_multiply<typename U::ratio, ratio<1, std::centi::den>>>;
|
using centi = prefix<si_prefix, ratio<1, std::centi::den>, "c">;
|
||||||
template<Unit U> using deca = unit<typename U::dimension, ratio_multiply<typename U::ratio, ratio<std::deca::num>>>;
|
using deci = prefix<si_prefix, ratio<1, std::deci::den>, "d">;
|
||||||
template<Unit U> using hecto = unit<typename U::dimension, ratio_multiply<typename U::ratio, ratio<std::hecto::num>>>;
|
using deca = prefix<si_prefix, ratio<std::deca::num>, "da">;
|
||||||
template<Unit U> using kilo = unit<typename U::dimension, ratio_multiply<typename U::ratio, ratio<std::kilo::num>>>;
|
using hecto = prefix<si_prefix, ratio<std::hecto::num>, "h">;
|
||||||
template<Unit U> using mega = unit<typename U::dimension, ratio_multiply<typename U::ratio, ratio<std::mega::num>>>;
|
using kilo = prefix<si_prefix, ratio<std::kilo::num>, "k">;
|
||||||
template<Unit U> using giga = unit<typename U::dimension, ratio_multiply<typename U::ratio, ratio<std::giga::num>>>;
|
using mega = prefix<si_prefix, ratio<std::mega::num>, "M">;
|
||||||
template<Unit U> using tera = unit<typename U::dimension, ratio_multiply<typename U::ratio, ratio<std::tera::num>>>;
|
using giga = prefix<si_prefix, ratio<std::giga::num>, "G">;
|
||||||
template<Unit U> using peta = unit<typename U::dimension, ratio_multiply<typename U::ratio, ratio<std::peta::num>>>;
|
using tera = prefix<si_prefix, ratio<std::tera::num>, "T">;
|
||||||
template<Unit U> using exa = unit<typename U::dimension, ratio_multiply<typename U::ratio, ratio<std::exa::num>>>;
|
using peta = prefix<si_prefix, ratio<std::peta::num>, "P">;
|
||||||
|
using exa = prefix<si_prefix, ratio<std::exa::num>, "E">;
|
||||||
|
|
||||||
template<> inline constexpr std::string_view prefix_symbol<si_prefix, ratio<1, std::atto::den>> = "a";
|
template<> inline constexpr std::string_view prefix_symbol<si_prefix, ratio<1, std::atto::den>> = "a";
|
||||||
template<> inline constexpr std::string_view prefix_symbol<si_prefix, ratio<1, std::femto::den>> = "f";
|
template<> inline constexpr std::string_view prefix_symbol<si_prefix, ratio<1, std::femto::den>> = "f";
|
||||||
template<> inline constexpr std::string_view prefix_symbol<si_prefix, ratio<1, std::pico::den>> = "p";
|
template<> inline constexpr std::string_view prefix_symbol<si_prefix, ratio<1, std::pico::den>> = "p";
|
||||||
template<> inline constexpr std::string_view prefix_symbol<si_prefix, ratio<1, std::nano::den>> = "n";
|
template<> inline constexpr std::string_view prefix_symbol<si_prefix, ratio<1, std::nano::den>> = "n";
|
||||||
template<> inline constexpr std::string_view prefix_symbol<si_prefix, ratio<1, std::micro::den>> = "\u00b5\u0073"; // µ
|
template<> inline constexpr std::string_view prefix_symbol<si_prefix, ratio<1, std::micro::den>> = "µ";
|
||||||
template<> inline constexpr std::string_view prefix_symbol<si_prefix, ratio<1, std::milli::den>> = "m";
|
template<> inline constexpr std::string_view prefix_symbol<si_prefix, ratio<1, std::milli::den>> = "m";
|
||||||
template<> inline constexpr std::string_view prefix_symbol<si_prefix, ratio<1, std::centi::den>> = "c";
|
template<> inline constexpr std::string_view prefix_symbol<si_prefix, ratio<1, std::centi::den>> = "c";
|
||||||
template<> inline constexpr std::string_view prefix_symbol<si_prefix, ratio<1, std::deci::den>> = "d";
|
template<> inline constexpr std::string_view prefix_symbol<si_prefix, ratio<1, std::deci::den>> = "d";
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/base_dimensions.h>
|
#include <units/dimensions/si_base_dimensions.h>
|
||||||
#include <units/quantity.h>
|
#include <units/quantity.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
@@ -32,7 +32,7 @@ namespace units {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept Substance = QuantityOf<T, substance>;
|
concept Substance = QuantityOf<T, substance>;
|
||||||
|
|
||||||
struct mole : coherent_derived_unit<mole, decltype("mol"_fs), substance, si_prefix> {};
|
struct mole : coherent_derived_unit<mole, "mol", substance, si_prefix> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/base_dimensions.h>
|
#include <units/dimensions/si_base_dimensions.h>
|
||||||
#include <units/quantity.h>
|
#include <units/quantity.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
@@ -32,7 +32,7 @@ namespace units {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept ThermodynamicTemperature = QuantityOf<T, temperature>;
|
concept ThermodynamicTemperature = QuantityOf<T, temperature>;
|
||||||
|
|
||||||
struct kelvin : coherent_derived_unit<kelvin, decltype("K"_fs), temperature> {};
|
struct kelvin : coherent_derived_unit<kelvin, "K", temperature> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -22,7 +22,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/base_dimensions.h>
|
#include <units/dimensions/si_base_dimensions.h>
|
||||||
|
#include <units/dimensions/si_prefixes.h>
|
||||||
#include <units/quantity.h>
|
#include <units/quantity.h>
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
@@ -32,12 +33,12 @@ namespace units {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept Time = QuantityOf<T, time>;
|
concept Time = QuantityOf<T, time>;
|
||||||
|
|
||||||
struct second : coherent_derived_unit<second, decltype("s"_fs), time, si_prefix> {};
|
struct second : coherent_derived_unit<second, "s", time, si_prefix> {};
|
||||||
struct nanosecond : derived_unit<nanosecond, decltype("ns"_fs), nano<second>> {};
|
struct nanosecond : prefixed_derived_unit<nanosecond, nano, second> {};
|
||||||
struct microsecond : derived_unit<microsecond, decltype("us"_fs), micro<second>> {};
|
struct microsecond : prefixed_derived_unit<microsecond, micro, second> {};
|
||||||
struct millisecond : derived_unit<millisecond, decltype("ms"_fs), milli<second>> {};
|
struct millisecond : prefixed_derived_unit<millisecond, milli, second> {};
|
||||||
struct minute : derived_unit<minute, decltype("min"_fs), time, ratio<60>> {};
|
struct minute : derived_unit<minute, "min", time, ratio<60>> {};
|
||||||
struct hour : derived_unit<hour, decltype("h"_fs), time, ratio<3600>> {};
|
struct hour : derived_unit<hour, "h", time, ratio<3600>> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -32,9 +32,9 @@ namespace units {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept Velocity = QuantityOf<T, velocity>;
|
concept Velocity = QuantityOf<T, velocity>;
|
||||||
|
|
||||||
struct metre_per_second : coherent_derived_unit<metre_per_second, decltype("m/s"_fs), velocity> {};
|
struct metre_per_second : coherent_derived_unit<metre_per_second, "m/s", velocity> {};
|
||||||
struct kilometre_per_hour : derived_unit<kilometre_per_hour, decltype("km/h"_fs), velocity, kilometre, hour> {};
|
struct kilometre_per_hour : deduced_derived_unit<kilometre_per_hour, "km/h", velocity, kilometre, hour> {};
|
||||||
struct mile_per_hour : derived_unit<mile_per_hour, decltype("mi/h"_fs), velocity, mile, hour> {};
|
struct mile_per_hour : deduced_derived_unit<mile_per_hour, "mi/h", velocity, mile, hour> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/dimensions/base_dimensions.h>
|
#include <units/dimensions/si_base_dimensions.h>
|
||||||
#include <units/dimensions/power.h>
|
#include <units/dimensions/power.h>
|
||||||
#include <units/dimensions/current.h>
|
#include <units/dimensions/current.h>
|
||||||
#include <units/dimensions/energy.h>
|
#include <units/dimensions/energy.h>
|
||||||
@@ -35,7 +35,7 @@ namespace units {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept Voltage = QuantityOf<T, voltage>;
|
concept Voltage = QuantityOf<T, voltage>;
|
||||||
|
|
||||||
struct volt : coherent_derived_unit<volt, decltype("V"_fs), voltage, si_prefix> {};
|
struct volt : coherent_derived_unit<volt, "V", voltage, si_prefix> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -31,11 +31,11 @@ namespace units {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept Volume = QuantityOf<T, volume>;
|
concept Volume = QuantityOf<T, volume>;
|
||||||
|
|
||||||
struct cubic_metre : coherent_derived_unit<cubic_metre, decltype("m^3"_fs), volume> {};
|
struct cubic_metre : coherent_derived_unit<cubic_metre, "m^3", volume> {};
|
||||||
struct cubic_millimetre : derived_unit<cubic_millimetre, decltype("mm^3"_fs), volume, millimetre> {};
|
struct cubic_millimetre : deduced_derived_unit<cubic_millimetre, "mm^3", volume, millimetre> {};
|
||||||
struct cubic_centimetre : derived_unit<cubic_centimetre, decltype("cm^3"_fs), volume, centimetre> {};
|
struct cubic_centimetre : deduced_derived_unit<cubic_centimetre, "cm^3", volume, centimetre> {};
|
||||||
struct cubic_kilometre : derived_unit<cubic_kilometre, decltype("km^3"_fs), volume, kilometre, metre> {};
|
struct cubic_kilometre : deduced_derived_unit<cubic_kilometre, "km^3", volume, kilometre, metre> {};
|
||||||
struct cubic_foot : derived_unit<cubic_foot, decltype("ft^3"_fs), volume, foot> {};
|
struct cubic_foot : deduced_derived_unit<cubic_foot, "ft^3", volume, foot> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -22,12 +22,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/quantity.h>
|
#include <ostream>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
namespace units {
|
namespace units {
|
||||||
|
|
||||||
template<typename Prefix, typename Ratio>
|
template<typename Prefix, Ratio R>
|
||||||
inline constexpr std::string_view prefix_symbol = "";
|
inline constexpr std::string_view prefix_symbol;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
@@ -44,13 +45,13 @@ namespace units {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ratio, typename Prefix, typename CharT, typename Traits>
|
template<typename Ratio, typename PrefixType, typename CharT, typename Traits>
|
||||||
void print_prefix_or_ratio(std::basic_ostream<CharT, Traits>& os)
|
void print_prefix_or_ratio(std::basic_ostream<CharT, Traits>& os)
|
||||||
{
|
{
|
||||||
if constexpr(Ratio::num != 1 || Ratio::den != 1) {
|
if constexpr(Ratio::num != 1 || Ratio::den != 1) {
|
||||||
constexpr auto prefix = prefix_symbol<Prefix, Ratio>;
|
constexpr auto prefix = prefix_symbol<PrefixType, Ratio>;
|
||||||
|
|
||||||
if constexpr(prefix != "") {
|
if constexpr(!prefix.empty()) {
|
||||||
// print as a prefixed unit
|
// print as a prefixed unit
|
||||||
os << prefix;
|
os << prefix;
|
||||||
}
|
}
|
||||||
@@ -77,7 +78,10 @@ namespace units {
|
|||||||
os << "^(" << abs(E::num) << "/" << E::den << ")";
|
os << "^(" << abs(E::num) << "/" << E::den << ")";
|
||||||
}
|
}
|
||||||
else if constexpr(abs(E::num) != 1) {
|
else if constexpr(abs(E::num) != 1) {
|
||||||
os << "^" << abs(E::num);
|
// if constexpr(is_unicode<CharT>)
|
||||||
|
// os << superscript<abs(E::num)>;
|
||||||
|
// else
|
||||||
|
os << "^" << abs(E::num);
|
||||||
}
|
}
|
||||||
first = false;
|
first = false;
|
||||||
};
|
};
|
||||||
|
@@ -23,7 +23,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <units/bits/concepts.h>
|
#include <units/bits/concepts.h>
|
||||||
#include <units/prefix.h>
|
#include <units/unit.h>
|
||||||
|
#include <units/format.h>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
@@ -283,7 +284,7 @@ namespace units {
|
|||||||
os << q.count() << " ";
|
os << q.count() << " ";
|
||||||
if constexpr(!detail::is_unit<quantity::unit>) {
|
if constexpr(!detail::is_unit<quantity::unit>) {
|
||||||
// print user-defined unit
|
// print user-defined unit
|
||||||
os << unit::symbol::c_str();
|
os << unit::symbol;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
using ratio = quantity::unit::ratio;
|
using ratio = quantity::unit::ratio;
|
||||||
@@ -291,8 +292,8 @@ namespace units {
|
|||||||
if constexpr(!detail::is_dimension<dim>) {
|
if constexpr(!detail::is_dimension<dim>) {
|
||||||
// print as a prefix or ratio of a coherent unit symbol defined by the user
|
// print as a prefix or ratio of a coherent unit symbol defined by the user
|
||||||
using coherent_unit = downcast_target<units::unit<dim, units::ratio<1>>>;
|
using coherent_unit = downcast_target<units::unit<dim, units::ratio<1>>>;
|
||||||
detail::print_prefix_or_ratio<ratio, typename coherent_unit::prefix>(os);
|
detail::print_prefix_or_ratio<ratio, typename coherent_unit::prefix_type>(os);
|
||||||
os << coherent_unit::symbol::c_str();
|
os << coherent_unit::symbol;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// print as a ratio of a coherent unit
|
// print as a ratio of a coherent unit
|
||||||
|
@@ -52,6 +52,30 @@ namespace units {
|
|||||||
std::is_empty_v<T> &&
|
std::is_empty_v<T> &&
|
||||||
detail::is_unit<downcast_base_t<T>>;
|
detail::is_unit<downcast_base_t<T>>;
|
||||||
|
|
||||||
|
template<typename PrefixType, Ratio R, basic_fixed_string Symbol>
|
||||||
|
struct prefix {
|
||||||
|
using prefix_type = PrefixType;
|
||||||
|
using ratio = R;
|
||||||
|
static constexpr auto symbol = Symbol;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// TODO gcc:92150
|
||||||
|
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92150
|
||||||
|
// namespace detail {
|
||||||
|
|
||||||
|
// template<typename T>
|
||||||
|
// inline constexpr bool is_prefix = false;
|
||||||
|
|
||||||
|
// template<typename PrefixType, Ratio R, basic_fixed_string Symbol>
|
||||||
|
// inline constexpr bool is_prefix<prefix<PrefixType, R, Symbol>> = true;
|
||||||
|
|
||||||
|
// } // namespace detail
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
// concept Prefix = detail::is_prefix<T>;
|
||||||
|
concept Prefix = true;
|
||||||
|
|
||||||
// make_derived_unit
|
// make_derived_unit
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@@ -115,56 +139,29 @@ namespace units {
|
|||||||
|
|
||||||
// derived_unit
|
// derived_unit
|
||||||
|
|
||||||
// TODO gcc:92101
|
|
||||||
// Gated by the following gcc bug
|
|
||||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92101
|
|
||||||
// template<typename Child, fixed_string Symbol, typename...>
|
|
||||||
// struct derived_unit;
|
|
||||||
|
|
||||||
// template<typename Child, fixed_string Symbol, Dimension D>
|
|
||||||
// struct derived_unit<Child, Symbol, D> : downcast_helper<Child, unit<D, ratio<1>>> {
|
|
||||||
// static constexpr auto symbol = Symbol;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// template<typename Child, fixed_string Symbol, Dimension D, Ratio R>
|
|
||||||
// struct derived_unit<Child, Symbol, D, R> : downcast_helper<Child, unit<D, R>> {
|
|
||||||
// static constexpr auto symbol = Symbol;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// template<typename Child, fixed_string Symbol, Unit U>
|
|
||||||
// struct derived_unit<Child, Symbol, U> : downcast_helper<Child, U> {
|
|
||||||
// static constexpr auto symbol = Symbol;
|
|
||||||
// };
|
|
||||||
|
|
||||||
// template<typename Child, fixed_string Symbol, Dimension D, Unit U, Unit... Us>
|
|
||||||
// struct derived_unit<Child, Symbol, D, U, Us...> : downcast_helper<Child, detail::make_derived_unit<D, U, Us...>> {
|
|
||||||
// static constexpr auto symbol = Symbol;
|
|
||||||
// };
|
|
||||||
|
|
||||||
struct no_prefix;
|
struct no_prefix;
|
||||||
|
|
||||||
template<typename Child, typename Symbol, Dimension D, typename Prefix = no_prefix>
|
template<typename Child, basic_fixed_string Symbol, Dimension D, typename PrefixType = no_prefix>
|
||||||
struct coherent_derived_unit : downcast_helper<Child, unit<D, ratio<1>>> {
|
struct coherent_derived_unit : downcast_helper<Child, unit<D, ratio<1>>> {
|
||||||
using symbol = Symbol;
|
static constexpr auto symbol = Symbol;
|
||||||
using prefix = Prefix;
|
using prefix_type = PrefixType;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Child, typename Symbol, typename...>
|
template<typename Child, basic_fixed_string Symbol, Dimension D, Ratio R>
|
||||||
struct derived_unit;
|
struct derived_unit : downcast_helper<Child, unit<D, R>> {
|
||||||
|
static constexpr auto symbol = Symbol;
|
||||||
template<typename Child, typename Symbol, Dimension D, Ratio R>
|
|
||||||
struct derived_unit<Child, Symbol, D, R> : downcast_helper<Child, unit<D, R>> {
|
|
||||||
using symbol = Symbol;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Child, typename Symbol, Unit U>
|
template<typename Child, Prefix P, Unit U>
|
||||||
struct derived_unit<Child, Symbol, U> : downcast_helper<Child, U> {
|
requires requires { U::symbol; } && std::same_as<typename U::prefix_type, typename P::prefix_type>
|
||||||
using symbol = Symbol;
|
struct prefixed_derived_unit : downcast_helper<Child, unit<typename U::dimension, ratio_multiply<typename P::ratio, typename U::ratio>>> {
|
||||||
|
static constexpr auto symbol = P::symbol + U::symbol;
|
||||||
|
using prefix_type = P::prefix_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Child, typename Symbol, Dimension D, Unit U, Unit... Us>
|
template<typename Child, basic_fixed_string Symbol, Dimension D, Unit U, Unit... Us>
|
||||||
struct derived_unit<Child, Symbol, D, U, Us...> : downcast_helper<Child, detail::make_derived_unit<D, U, Us...>> {
|
struct deduced_derived_unit : downcast_helper<Child, detail::make_derived_unit<D, U, Us...>> {
|
||||||
using symbol = Symbol;
|
static constexpr auto symbol = Symbol;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace units
|
} // namespace units
|
||||||
|
@@ -33,13 +33,11 @@ namespace data {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept DigitalInformation = units::QuantityOf<T, digital_information>;
|
concept DigitalInformation = units::QuantityOf<T, digital_information>;
|
||||||
|
|
||||||
using namespace units::hacks;
|
|
||||||
|
|
||||||
struct data_prefix;
|
struct data_prefix;
|
||||||
|
|
||||||
struct bit : units::coherent_derived_unit<bit, decltype("b"_fs), digital_information, data_prefix> {};
|
struct bit : units::coherent_derived_unit<bit, "b", digital_information, data_prefix> {};
|
||||||
struct kilobit : units::derived_unit<bit, decltype("Kib"_fs), digital_information, units::ratio<1'024>> {};
|
struct kilobit : units::derived_unit<bit, "Kib", digital_information, units::ratio<1'024>> {};
|
||||||
struct byte : units::derived_unit<byte, decltype("B"_fs), digital_information, units::ratio<8>> {};
|
struct byte : units::derived_unit<byte, "B", digital_information, units::ratio<8>> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
|
@@ -48,6 +48,12 @@ TEST_CASE("operator<< on a quantity", "[text][ostream]")
|
|||||||
stream << 72.5kJ;
|
stream << 72.5kJ;
|
||||||
REQUIRE(stream.str() == "72.5 kJ");
|
REQUIRE(stream.str() == "72.5 kJ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("unit with a prefix")
|
||||||
|
{
|
||||||
|
stream << 125us;
|
||||||
|
REQUIRE(stream.str() == "125 µs");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("quantity with a predefined dimension but unknown unit")
|
SECTION("quantity with a predefined dimension but unknown unit")
|
||||||
@@ -172,4 +178,13 @@ TEST_CASE("operator<< on a quantity", "[text][ostream]")
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// Restate operator<< definitions in terms of std::format to make I/O manipulators apply to whole objects
|
// Restate operator<< definitions in terms of std::format to make I/O manipulators apply to whole objects
|
||||||
// rather than their parts
|
// rather than their parts
|
||||||
|
|
||||||
|
|
||||||
|
// Giving a precision specification
|
||||||
|
// in the chrono-format-spec is valid only for std::chrono::duration types where the representation type Rep
|
||||||
|
// is a floating-point type. For all other Rep types, a format_error shall be thrown if the chrono-format-spec
|
||||||
|
// contains a precision specification.
|
||||||
|
|
||||||
|
// string s = format("{:=>8}", 42ms); // value of s is "====42ms"
|
||||||
|
|
||||||
|
@@ -35,12 +35,10 @@ namespace {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
concept DigitalInformation = units::QuantityOf<T, digital_information>;
|
concept DigitalInformation = units::QuantityOf<T, digital_information>;
|
||||||
|
|
||||||
using namespace units::hacks;
|
|
||||||
|
|
||||||
struct data_prefix {};
|
struct data_prefix {};
|
||||||
|
|
||||||
struct bit : units::coherent_derived_unit<bit, decltype("b"_fs), digital_information, data_prefix> {};
|
struct bit : units::coherent_derived_unit<bit, "b", digital_information, data_prefix> {};
|
||||||
struct byte : units::derived_unit<byte, decltype("B"_fs), digital_information, units::ratio<8>> {};
|
struct byte : units::derived_unit<byte, "B", digital_information, units::ratio<8>> {};
|
||||||
|
|
||||||
inline namespace literals {
|
inline namespace literals {
|
||||||
|
|
||||||
@@ -65,11 +63,11 @@ namespace {
|
|||||||
|
|
||||||
// power spectral density
|
// power spectral density
|
||||||
struct power_spectral_density : derived_dimension<power_spectral_density, units::exp<voltage, 2>, units::exp<frequency, -1>> {};
|
struct power_spectral_density : derived_dimension<power_spectral_density, units::exp<voltage, 2>, units::exp<frequency, -1>> {};
|
||||||
struct sq_volt_per_hertz : coherent_derived_unit<sq_volt_per_hertz, decltype("V^2/Hz"_fs), power_spectral_density> {};
|
struct sq_volt_per_hertz : coherent_derived_unit<sq_volt_per_hertz, "V^2/Hz", power_spectral_density> {};
|
||||||
|
|
||||||
// amplitude spectral density
|
// amplitude spectral density
|
||||||
struct amplitude_spectral_density : derived_dimension<amplitude_spectral_density, units::exp<voltage, 1>, units::exp<frequency, -1, 2>> {};
|
struct amplitude_spectral_density : derived_dimension<amplitude_spectral_density, units::exp<voltage, 1>, units::exp<frequency, -1, 2>> {};
|
||||||
struct volt_per_sqrt_hertz : coherent_derived_unit<volt_per_sqrt_hertz, decltype("V/Hz^(1/2)"_fs), amplitude_spectral_density> {};
|
struct volt_per_sqrt_hertz : coherent_derived_unit<volt_per_sqrt_hertz, "V/Hz^(1/2)", amplitude_spectral_density> {};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
Reference in New Issue
Block a user