feat: natural units support is now opt-in

This commit is contained in:
Mateusz Pusz
2025-07-09 20:05:03 +02:00
parent 3fdf2debd8
commit e058a47baf
26 changed files with 222 additions and 95 deletions

View File

@@ -61,6 +61,7 @@ class MPUnitsConan(ConanFile):
"no_crtp": [True, False],
"contracts": ["none", "gsl-lite", "ms-gsl"],
"freestanding": [True, False],
"natural_units": [True, False],
}
default_options = {
# "cxx_modules" default set in config_options()
@@ -69,6 +70,7 @@ class MPUnitsConan(ConanFile):
# "no_crtp" default set in config_options()
"contracts": "gsl-lite",
"freestanding": False,
"natural_units": True,
}
implements = ["auto_header_only"]
exports = "LICENSE.md"
@@ -281,6 +283,7 @@ class MPUnitsConan(ConanFile):
tc.cache_variables["MP_UNITS_API_STD_FORMAT"] = opt.std_format
tc.cache_variables["MP_UNITS_API_NO_CRTP"] = opt.no_crtp
tc.cache_variables["MP_UNITS_API_CONTRACTS"] = str(opt.contracts).upper()
tc.cache_variables["MP_UNITS_API_NATURAL_UNITS"] = opt.natural_units
tc.generate()
deps = CMakeDeps(self)

View File

@@ -154,6 +154,14 @@ dependencies by other means, some modifications to the library's CMake files mig
[conan freestanding]: https://github.com/mpusz/mp-units/releases/tag/v2.2.0
[`natural_units`](#natural_units){ #natural_units }
: [:octicons-tag-24: 2.5.0][conan natural units] · :octicons-milestone-24: `ON`/`OFF` (Default: `ON`)
Enables experimental natural units systems support.
[conan natural units]: https://github.com/mpusz/mp-units/releases/tag/v2.5.0
??? info "CMake options to set when Conan is not being used"
### CMake options
@@ -215,6 +223,14 @@ dependencies by other means, some modifications to the library's CMake files mig
[cmake freestanding]: https://github.com/mpusz/mp-units/releases/tag/v2.2.0
[`MP_UNITS_API_NATURAL_UNITS`](#MP_UNITS_API_NATURAL_UNITS){ #MP_UNITS_API_NATURAL_UNITS }
: [:octicons-tag-24: 2.5.0][cmake natural units] · :octicons-milestone-24: `ON`/`OFF` (Default: `ON`)
Enables experimental natural units systems support.
[cmake natural units]: https://github.com/mpusz/mp-units/releases/tag/v2.5.0
## Installation and reuse

View File

@@ -69,7 +69,9 @@ add_example(si_constants)
add_example(spectroscopy_units)
add_example(storage_tank)
add_example(strong_angular_quantities)
add_example(total_energy)
if(${projectPrefix}API_NATURAL_UNITS)
add_example(total_energy)
endif()
add_example(unmanned_aerial_vehicle example_utils)
add_subdirectory(glide_computer_lib)

View File

@@ -87,12 +87,14 @@ option(${projectPrefix}API_THROWING_CONSTRAINTS "Enable throwing constraints"
option(${projectPrefix}API_FREESTANDING "Builds only freestanding part of the library" OFF)
set(${projectPrefix}API_CONTRACTS GSL-LITE CACHE STRING "Enable contract checking")
check_cache_var_values(API_CONTRACTS NONE GSL-LITE MS-GSL)
option(${projectPrefix}API_NATURAL_UNITS "Enables natural units support" ON)
message(STATUS "${projectPrefix}API_STD_FORMAT: ${${projectPrefix}API_STD_FORMAT}")
message(STATUS "${projectPrefix}API_NO_CRTP: ${${projectPrefix}API_NO_CRTP}")
message(STATUS "${projectPrefix}API_THROWING_CONSTRAINTS: ${${projectPrefix}API_THROWING_CONSTRAINTS}")
message(STATUS "${projectPrefix}API_FREESTANDING: ${${projectPrefix}API_FREESTANDING}")
message(STATUS "${projectPrefix}API_CONTRACTS: ${${projectPrefix}API_CONTRACTS}")
message(STATUS "${projectPrefix}API_NATURAL_UNITS: ${${projectPrefix}API_NATURAL_UNITS}")
# validate options
if(${projectPrefix}API_FREESTANDING AND NOT ${projectPrefix}API_CONTRACTS STREQUAL "NONE")

View File

@@ -67,7 +67,6 @@ add_mp_units_module(
include/mp-units/framework/representation_concepts.h
include/mp-units/framework/symbol_text.h
include/mp-units/framework/symbolic_expression.h
include/mp-units/framework/system_reference.h
include/mp-units/framework/unit.h
include/mp-units/framework/unit_concepts.h
include/mp-units/framework/unit_magnitude.h
@@ -81,6 +80,13 @@ add_mp_units_module(
MODULE_INTERFACE_UNIT mp-units-core.cpp
)
if(${${projectPrefix}API_NATURAL_UNITS})
target_sources(
mp-units-core PUBLIC FILE_SET HEADERS BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include FILES
include/mp-units/framework/system_reference.h
)
endif()
if(NOT ${projectPrefix}API_FREESTANDING)
target_sources(
mp-units-core
@@ -171,6 +177,14 @@ if(${projectPrefix}API_THROWING_CONSTRAINTS)
)
endif()
# Natural units support
if(${${projectPrefix}API_NATURAL_UNITS})
target_compile_definitions(
mp-units-core ${${projectPrefix}TARGET_SCOPE}
${projectPrefix}API_NATURAL_UNITS=$<BOOL:${${projectPrefix}API_NATURAL_UNITS}>
)
endif()
# https://github.com/llvm/llvm-project/issues/131410
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 20
AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 20.2

View File

@@ -22,6 +22,7 @@
#pragma once
#include <mp-units/compat_macros.h>
#include <mp-units/framework/quantity_spec.h>
#include <mp-units/framework/symbolic_expression.h>
#include <mp-units/framework/unit_concepts.h>
@@ -33,7 +34,7 @@ struct common_unit;
namespace detail {
template<AssociatedUnit U>
template<MP_UNITS_ASSOCIATED_UNIT U>
[[nodiscard]] consteval auto get_associated_quantity(U u);
template<typename... Us>
@@ -42,10 +43,10 @@ template<typename... Us>
return get_common_quantity_spec(get_associated_quantity(Us{})...);
}
template<AssociatedUnit U>
template<MP_UNITS_ASSOCIATED_UNIT U>
using to_quantity_spec = decltype(get_associated_quantity(U{}));
template<AssociatedUnit U>
template<MP_UNITS_ASSOCIATED_UNIT U>
[[nodiscard]] consteval auto get_associated_quantity_impl(U u)
{
if constexpr (requires { U::_quantity_spec_; })
@@ -56,10 +57,10 @@ template<AssociatedUnit U>
return expr_map<to_quantity_spec, derived_quantity_spec, struct dimensionless>(u);
}
template<AssociatedUnit U>
template<MP_UNITS_ASSOCIATED_UNIT U>
constexpr auto get_associated_quantity_result = get_associated_quantity_impl(U{});
template<AssociatedUnit U>
template<MP_UNITS_ASSOCIATED_UNIT U>
[[nodiscard]] consteval auto get_associated_quantity(U)
{
return get_associated_quantity_result<U>;

View File

@@ -158,6 +158,13 @@ MP_UNITS_DIAGNOSTIC_POP
#endif
#if !defined MP_UNITS_API_NATURAL_UNITS
#define MP_UNITS_API_NATURAL_UNITS 1
#endif
#if defined(__clang__) && defined(__apple_build_version__) && __apple_build_version__ < 16000026
#define MP_UNITS_XCODE15_HACKS
#endif

View File

@@ -40,6 +40,20 @@
#endif
#if MP_UNITS_API_NATURAL_UNITS
#define MP_UNITS_ASSOCIATED_UNIT AssociatedUnit
#define MP_UNITS_ASSOCIATED_UNIT_T(U) AssociatedUnit<U>
#define MP_UNITS_WEAK_UNIT_OF(...) detail::WeakUnitOf<__VA_ARGS__>
#else
#define MP_UNITS_ASSOCIATED_UNIT Unit
#define MP_UNITS_ASSOCIATED_UNIT_T(U) Unit<U>
#define MP_UNITS_WEAK_UNIT_OF(...) UnitOf<__VA_ARGS__>
#endif
#if MP_UNITS_HOSTED
#define MP_UNITS_THROW(expr) throw expr
#else

View File

@@ -39,7 +39,9 @@
#include <mp-units/framework/representation_concepts.h>
#include <mp-units/framework/symbol_text.h>
#include <mp-units/framework/symbolic_expression.h>
#if MP_UNITS_API_NATURAL_UNITS
#include <mp-units/framework/system_reference.h>
#endif
#include <mp-units/framework/unit.h>
#include <mp-units/framework/unit_concepts.h>
#include <mp-units/framework/unit_magnitude.h>

View File

@@ -244,7 +244,7 @@ public:
return *this;
}
template<detail::WeakUnitOf<quantity_spec> ToU>
template<MP_UNITS_WEAK_UNIT_OF(quantity_spec) ToU>
requires detail::ValuePreservingScaling<unit, ToU{}, rep>
[[nodiscard]] constexpr QuantityOf<quantity_spec> auto in(ToU) const
{
@@ -258,7 +258,7 @@ public:
return quantity<reference, ToRep>{*this};
}
template<RepresentationOf<quantity_spec> ToRep, detail::WeakUnitOf<quantity_spec> ToU>
template<RepresentationOf<quantity_spec> ToRep, MP_UNITS_WEAK_UNIT_OF(quantity_spec) ToU>
requires detail::ValuePreservingConstruction<ToRep, rep> &&
detail::ValuePreservingConversion<unit, rep, ToU{}, ToRep>
[[nodiscard]] constexpr QuantityOf<quantity_spec> auto in(ToU) const
@@ -266,7 +266,7 @@ public:
return quantity<detail::make_reference(quantity_spec, ToU{}), ToRep>{*this};
}
template<detail::WeakUnitOf<quantity_spec> ToU>
template<MP_UNITS_WEAK_UNIT_OF(quantity_spec) ToU>
requires detail::SaneScaling<unit, ToU{}, rep>
[[nodiscard]] constexpr QuantityOf<quantity_spec> auto force_in(ToU) const
{
@@ -280,7 +280,7 @@ public:
return value_cast<ToRep>(*this);
}
template<RepresentationOf<quantity_spec> ToRep, detail::WeakUnitOf<quantity_spec> ToU>
template<RepresentationOf<quantity_spec> ToRep, MP_UNITS_WEAK_UNIT_OF(quantity_spec) ToU>
requires std::constructible_from<ToRep, rep> && detail::SaneScaling<unit, ToU{}, rep>
[[nodiscard]] constexpr QuantityOf<quantity_spec> auto force_in(ToU) const
{
@@ -311,14 +311,14 @@ public:
= delete;
#endif
template<detail::WeakUnitOf<quantity_spec> U>
template<MP_UNITS_WEAK_UNIT_OF(quantity_spec) U>
requires detail::ValuePreservingScaling<unit, U{}, rep>
[[nodiscard]] constexpr rep numerical_value_in(U) const noexcept
{
return in(U{}).numerical_value_is_an_implementation_detail_;
}
template<detail::WeakUnitOf<quantity_spec> U>
template<MP_UNITS_WEAK_UNIT_OF(quantity_spec) U>
requires detail::SaneScaling<unit, U{}, rep>
[[nodiscard]] constexpr rep force_numerical_value_in(U) const noexcept
{

View File

@@ -24,6 +24,7 @@
// IWYU pragma: private, include <mp-units/framework.h>
#include <mp-units/bits/module_macros.h>
#include <mp-units/compat_macros.h>
#include <mp-units/framework/quantity_concepts.h>
#include <mp-units/framework/quantity_point_concepts.h>
#include <mp-units/framework/reference.h>
@@ -57,7 +58,7 @@ namespace mp_units {
* @tparam ToQS a quantity specification to use for a target quantity
*/
template<QuantitySpec auto ToQS, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
requires(castable(Q::quantity_spec, ToQS)) && detail::WeakUnitOf<MP_UNITS_NONCONST_TYPE(Q::unit), ToQS>
requires(castable(Q::quantity_spec, ToQS)) && (MP_UNITS_WEAK_UNIT_OF(MP_UNITS_NONCONST_TYPE(Q::unit), ToQS))
[[nodiscard]] constexpr Quantity auto quantity_cast(FwdQ&& q)
{
return quantity{std::forward<FwdQ>(q).numerical_value_is_an_implementation_detail_, make_reference(ToQS, Q::unit)};
@@ -81,7 +82,7 @@ template<QuantitySpec auto ToQS, typename FwdQ, Quantity Q = std::remove_cvref_t
* @tparam ToQS a quantity specification to use for a target quantity point
*/
template<QuantitySpec auto ToQS, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
requires(castable(QP::quantity_spec, ToQS)) && detail::WeakUnitOf<MP_UNITS_NONCONST_TYPE(QP::unit), ToQS>
requires(castable(QP::quantity_spec, ToQS)) && (MP_UNITS_WEAK_UNIT_OF(MP_UNITS_NONCONST_TYPE(QP::unit), ToQS))
[[nodiscard]] constexpr QuantityPoint auto quantity_cast(FwdQP&& qp)
{
return QP{quantity_cast<ToQS>(std::forward<FwdQP>(qp).quantity_from_origin_is_an_implementation_detail_),

View File

@@ -25,6 +25,7 @@
// IWYU pragma: private, include <mp-units/framework.h>
#include <mp-units/bits/hacks.h>
#include <mp-units/bits/module_macros.h>
#include <mp-units/compat_macros.h>
#include <mp-units/framework/compare.h>
#include <mp-units/framework/customization_points.h>
#include <mp-units/framework/quantity.h>
@@ -328,7 +329,7 @@ public:
}
// unit conversions
template<detail::WeakUnitOf<quantity_spec> ToU>
template<MP_UNITS_WEAK_UNIT_OF(quantity_spec) ToU>
requires detail::ValuePreservingScaling<unit, ToU{}, rep>
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto in(ToU) const
{
@@ -342,7 +343,7 @@ public:
return ::mp_units::quantity_point{quantity_ref_from(point_origin).template in<ToRep>(), point_origin};
}
template<RepresentationOf<quantity_spec> ToRep, detail::WeakUnitOf<quantity_spec> ToU>
template<RepresentationOf<quantity_spec> ToRep, MP_UNITS_WEAK_UNIT_OF(quantity_spec) ToU>
requires detail::ValuePreservingConstruction<ToRep, rep> &&
detail::ValuePreservingConversion<unit, rep, ToU{}, ToRep>
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto in(ToU) const
@@ -350,7 +351,7 @@ public:
return ::mp_units::quantity_point{quantity_ref_from(point_origin).template in<ToRep>(ToU{}), point_origin};
}
template<detail::WeakUnitOf<quantity_spec> ToU>
template<MP_UNITS_WEAK_UNIT_OF(quantity_spec) ToU>
requires detail::SaneScaling<unit, ToU{}, rep>
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto force_in(ToU) const
{
@@ -364,7 +365,7 @@ public:
return ::mp_units::quantity_point{quantity_ref_from(point_origin).template force_in<ToRep>(), point_origin};
}
template<RepresentationOf<quantity_spec> ToRep, detail::WeakUnitOf<quantity_spec> ToU>
template<RepresentationOf<quantity_spec> ToRep, MP_UNITS_WEAK_UNIT_OF(quantity_spec) ToU>
requires std::constructible_from<ToRep, rep> && detail::SaneScaling<unit, ToU{}, rep>
[[nodiscard]] constexpr QuantityPointOf<quantity_spec> auto force_in(ToU) const
{

View File

@@ -23,6 +23,7 @@
#pragma once
// IWYU pragma: private, include <mp-units/framework.h>
#include <mp-units/compat_macros.h>
#include <mp-units/bits/hacks.h>
#include <mp-units/bits/module_macros.h>
#include <mp-units/bits/quantity_spec_hierarchy.h>
@@ -107,7 +108,7 @@ concept DerivedQuantitySpec =
(QuantityKindSpec<T> && is_specialization_of<MP_UNITS_NONCONST_TYPE(T::_quantity_spec_), derived_quantity_spec>));
template<QuantitySpec QS, detail::WeakUnitOf<QS{}> U>
template<QuantitySpec QS, MP_UNITS_WEAK_UNIT_OF(QS{}) U>
[[nodiscard]] consteval Reference auto make_reference(QS, U u)
{
if constexpr (requires { requires(mp_units::get_quantity_spec(U{}) == QS{}); })

View File

@@ -23,6 +23,7 @@
#pragma once
// IWYU pragma: private, include <mp-units/framework.h>
#include <mp-units/compat_macros.h>
#include <mp-units/bits/get_associated_quantity.h>
#include <mp-units/bits/module_macros.h>
#include <mp-units/framework/quantity_concepts.h>
@@ -49,7 +50,7 @@ using reference_t = reference<MP_UNITS_REMOVE_CONST(decltype(Q)), MP_UNITS_REMOV
MP_UNITS_EXPORT_BEGIN
template<AssociatedUnit U>
template<MP_UNITS_ASSOCIATED_UNIT U>
[[nodiscard]] consteval QuantitySpec auto get_quantity_spec(U)
{
return kind_of<detail::get_associated_quantity(U{})>;
@@ -81,7 +82,7 @@ struct reference {
return Q{} == Q2{} && U{} == U2{};
}
template<AssociatedUnit U2>
template<MP_UNITS_ASSOCIATED_UNIT U2>
[[nodiscard]] friend consteval bool operator==(reference, U2 u2)
{
return Q{} == get_quantity_spec(u2) && U{} == u2;
@@ -95,7 +96,7 @@ struct reference {
return {};
}
template<AssociatedUnit U2>
template<MP_UNITS_ASSOCIATED_UNIT U2>
[[nodiscard]] friend consteval detail::reference_t<(MP_UNITS_EXPRESSION_WORKAROUND(Q{} * get_quantity_spec(U2{}))),
MP_UNITS_EXPRESSION_WORKAROUND(U{} * U2{})>
operator*(reference, U2)
@@ -103,7 +104,7 @@ struct reference {
return {};
}
template<AssociatedUnit U1>
template<MP_UNITS_ASSOCIATED_UNIT U1>
[[nodiscard]] friend consteval detail::reference_t<MP_UNITS_EXPRESSION_WORKAROUND(get_quantity_spec(U1{}) * Q{}),
MP_UNITS_EXPRESSION_WORKAROUND(U1{} * U{})>
operator*(U1, reference)
@@ -119,7 +120,7 @@ struct reference {
return {};
}
template<AssociatedUnit U2>
template<MP_UNITS_ASSOCIATED_UNIT U2>
[[nodiscard]] friend consteval detail::reference_t<MP_UNITS_EXPRESSION_WORKAROUND(Q{} / get_quantity_spec(U2{})),
MP_UNITS_EXPRESSION_WORKAROUND(U{} / U2{})>
operator/(reference, U2)
@@ -127,7 +128,7 @@ struct reference {
return {};
}
template<AssociatedUnit U1>
template<MP_UNITS_ASSOCIATED_UNIT U1>
[[nodiscard]] friend consteval detail::reference_t<MP_UNITS_EXPRESSION_WORKAROUND(get_quantity_spec(U1{}) / Q{}),
MP_UNITS_EXPRESSION_WORKAROUND(U1{} / U{})>
operator/(U1, reference)
@@ -266,8 +267,9 @@ template<Reference R, typename Q>
// NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
constexpr auto operator/(R, Q&& q) = delete;
[[nodiscard]] consteval AssociatedUnit auto get_common_reference(AssociatedUnit auto u1, AssociatedUnit auto u2,
AssociatedUnit auto... rest)
[[nodiscard]] consteval MP_UNITS_ASSOCIATED_UNIT auto get_common_reference(MP_UNITS_ASSOCIATED_UNIT auto u1,
MP_UNITS_ASSOCIATED_UNIT auto u2,
MP_UNITS_ASSOCIATED_UNIT auto... rest)
requires requires {
get_common_quantity_spec(get_quantity_spec(u1), get_quantity_spec(u2), get_quantity_spec(rest)...);
get_common_unit(u1, u2, rest...);
@@ -278,10 +280,12 @@ constexpr auto operator/(R, Q&& q) = delete;
template<Reference R1, Reference R2, Reference... Rest>
[[nodiscard]] consteval Reference auto get_common_reference(R1 r1, R2 r2, Rest... rest)
requires(!(AssociatedUnit<R1> && AssociatedUnit<R2> && (... && AssociatedUnit<Rest>))) && requires {
get_common_quantity_spec(get_quantity_spec(r1), get_quantity_spec(r2), get_quantity_spec(rest)...);
get_common_unit(get_unit(r1), get_unit(r2), get_unit(rest)...);
}
requires(!(MP_UNITS_ASSOCIATED_UNIT_T(R1) && MP_UNITS_ASSOCIATED_UNIT_T(R2) &&
(... && MP_UNITS_ASSOCIATED_UNIT_T(Rest)))) &&
requires {
get_common_quantity_spec(get_quantity_spec(r1), get_quantity_spec(r2), get_quantity_spec(rest)...);
get_common_unit(get_unit(r1), get_unit(r2), get_unit(rest)...);
}
{
return detail::reference_t<get_common_quantity_spec(get_quantity_spec(R1{}), get_quantity_spec(R2{}),
get_quantity_spec(rest)...),
@@ -292,7 +296,7 @@ MP_UNITS_EXPORT_END
namespace detail {
template<AssociatedUnit auto To, AssociatedUnit From>
template<MP_UNITS_ASSOCIATED_UNIT auto To, MP_UNITS_ASSOCIATED_UNIT From>
[[nodiscard]] consteval MP_UNITS_REMOVE_CONST(decltype(To)) clone_reference_with(From)
{
return {};

View File

@@ -23,6 +23,7 @@
#pragma once
// IWYU pragma: private, include <mp-units/framework.h>
#include <mp-units/compat_macros.h>
#include <mp-units/bits/module_macros.h>
#include <mp-units/framework/quantity_spec_concepts.h>
#include <mp-units/framework/unit_concepts.h>
@@ -34,7 +35,7 @@ struct reference;
MP_UNITS_EXPORT_BEGIN
template<AssociatedUnit U>
template<MP_UNITS_ASSOCIATED_UNIT U>
[[nodiscard]] consteval QuantitySpec auto get_quantity_spec(U);
template<typename Q, typename U>
@@ -43,7 +44,7 @@ template<typename Q, typename U>
return Q{};
}
[[nodiscard]] consteval Unit auto get_unit(AssociatedUnit auto u) { return u; }
[[nodiscard]] consteval Unit auto get_unit(MP_UNITS_ASSOCIATED_UNIT auto u) { return u; }
template<typename Q, typename U>
[[nodiscard]] consteval Unit auto get_unit(reference<Q, U>)
@@ -57,7 +58,7 @@ template<typename Q, typename U>
* Satisfied by all specializations of @c reference.
*/
template<typename T>
concept Reference = AssociatedUnit<T> || is_specialization_of<T, reference>;
concept Reference = MP_UNITS_ASSOCIATED_UNIT_T(T) || is_specialization_of<T, reference>;
/**
* @brief A concept matching all references of the provided quantity spec

View File

@@ -23,12 +23,15 @@
#pragma once
// IWYU pragma: private, include <mp-units/framework.h>
#include <mp-units/compat_macros.h>
#include <mp-units/bits/hacks.h>
#include <mp-units/bits/module_macros.h>
#include <mp-units/framework/quantity_spec.h>
#include <mp-units/framework/reference.h>
#include <mp-units/framework/unit.h>
#if MP_UNITS_API_NATURAL_UNITS
MP_UNITS_EXPORT
namespace mp_units {
@@ -60,7 +63,7 @@ namespace mp_units {
* @tparam CoU coherent unit for a quantity in this system
*/
template<QuantitySpec auto Q, Unit auto CoU>
requires(!AssociatedUnit<decltype(CoU)>) || (CoU == one)
requires(!MP_UNITS_ASSOCIATED_UNIT_T(decltype(CoU))) || (CoU == one)
struct system_reference {
static constexpr auto quantity_spec = Q;
static constexpr auto coherent_unit = CoU;
@@ -77,3 +80,5 @@ struct system_reference {
};
} // namespace mp_units
#endif // MP_UNITS_API_NATURAL_UNITS

View File

@@ -23,6 +23,7 @@
#pragma once
// IWYU pragma: private, include <mp-units/framework.h>
#include <mp-units/compat_macros.h>
#include <mp-units/bits/get_associated_quantity.h>
#include <mp-units/bits/hacks.h>
#include <mp-units/bits/module_macros.h>
@@ -316,6 +317,8 @@ struct named_unit<Symbol, QS, PO> : detail::unit_interface {
static constexpr auto _point_origin_ = PO;
};
#if MP_UNITS_API_NATURAL_UNITS
/**
* @brief Specialization for a unit that can be reused by several base quantities
*
@@ -333,6 +336,8 @@ struct named_unit<Symbol> : detail::unit_interface {
static constexpr auto _symbol_ = Symbol; ///< Unique base unit identifier
};
#endif // MP_UNITS_API_NATURAL_UNITS
/**
* @brief Specialization for a unit with special name
*
@@ -365,7 +370,7 @@ struct named_unit<Symbol, U, PO> : decltype(U)::_base_type_ {
* @tparam Unit a unit for which we provide a special name
* @tparam QuantitySpec a specification of a quantity to be measured with this unit
*/
template<symbol_text Symbol, AssociatedUnit auto U, detail::QuantityKindSpec auto QS>
template<symbol_text Symbol, MP_UNITS_ASSOCIATED_UNIT auto U, detail::QuantityKindSpec auto QS>
requires(!Symbol.empty()) && (QS.dimension == detail::get_associated_quantity(U).dimension)
struct named_unit<Symbol, U, QS> : decltype(U)::_base_type_ {
using _base_type_ = named_unit; // exposition only
@@ -373,7 +378,7 @@ struct named_unit<Symbol, U, QS> : decltype(U)::_base_type_ {
static constexpr auto _quantity_spec_ = QS;
};
template<symbol_text Symbol, AssociatedUnit auto U, detail::QuantityKindSpec auto QS, PointOrigin auto PO>
template<symbol_text Symbol, MP_UNITS_ASSOCIATED_UNIT auto U, detail::QuantityKindSpec auto QS, PointOrigin auto PO>
requires(!Symbol.empty()) && (QS.dimension == detail::get_associated_quantity(U).dimension)
struct named_unit<Symbol, U, QS, PO> : decltype(U)::_base_type_ {
using _base_type_ = named_unit; // exposition only

View File

@@ -25,6 +25,7 @@
// IWYU pragma: private, include <mp-units/framework.h>
#include <mp-units/bits/module_macros.h>
#include <mp-units/bits/unsatisfied.h>
#include <mp-units/compat_macros.h>
#include <mp-units/framework/quantity_spec_concepts.h>
#include <mp-units/framework/symbolic_expression.h>
#include <mp-units/framework/unit_magnitude.h>
@@ -54,6 +55,8 @@ struct named_unit;
MP_UNITS_EXPORT template<typename T>
concept PrefixableUnit = Unit<T> && is_derived_from_specialization_of_v<T, named_unit>;
#if MP_UNITS_API_NATURAL_UNITS
namespace detail {
template<Unit U>
@@ -91,6 +94,8 @@ template<Unit U>
MP_UNITS_EXPORT template<typename U>
concept AssociatedUnit = Unit<U> && detail::has_associated_quantity(U{});
#endif
/**
* @brief A concept matching all units associated with the provided quantity spec
*
@@ -99,17 +104,21 @@ concept AssociatedUnit = Unit<U> && detail::has_associated_quantity(U{});
*/
MP_UNITS_EXPORT template<typename U, auto QS>
concept UnitOf =
AssociatedUnit<U> && QuantitySpec<MP_UNITS_REMOVE_CONST(decltype(QS))> &&
MP_UNITS_ASSOCIATED_UNIT<U> && QuantitySpec<MP_UNITS_REMOVE_CONST(decltype(QS))> &&
(implicitly_convertible(get_quantity_spec(U{}), QS) ||
(unsatisfied<"Unit '{}' is associated with quantity of kind '{}' which is not convertible to the '{}' quantity">(
U{}, type_name(get_quantity_spec(U{})._quantity_spec_), type_name(QS))));
namespace detail {
#if MP_UNITS_API_NATURAL_UNITS
template<typename U, auto QS>
concept WeakUnitOf =
Unit<U> && QuantitySpec<MP_UNITS_REMOVE_CONST(decltype(QS))> && ((!AssociatedUnit<U>) || UnitOf<U, QS>);
#endif
template<auto U1, auto U2>
concept UnitsOfCompatibleQuantities =
explicitly_convertible(get_quantity_spec(U1), get_quantity_spec(U2)) ||
@@ -126,9 +135,10 @@ concept ConvertibleUnits = (get_canonical_unit(U1).reference_unit == get_canonic
template<typename U1, auto U2>
concept UnitConvertibleTo =
Unit<U1> && Unit<MP_UNITS_REMOVE_CONST(decltype(U2))> &&
((U1{} == U2) || ((!AssociatedUnit<U1> || !AssociatedUnit<MP_UNITS_REMOVE_CONST(decltype(U2))> ||
UnitsOfCompatibleQuantities<U1{}, U2>) &&
ConvertibleUnits<U1{}, U2>));
((U1{} == U2) ||
((!MP_UNITS_ASSOCIATED_UNIT_T(U1) || !MP_UNITS_ASSOCIATED_UNIT_T(MP_UNITS_REMOVE_CONST(decltype(U2))) ||
UnitsOfCompatibleQuantities<U1{}, U2>) &&
ConvertibleUnits<U1{}, U2>));
template<typename T>
concept OffsetUnit = Unit<T> && requires { T::_point_origin_; };

View File

@@ -25,6 +25,7 @@
// IWYU pragma: private, include <mp-units/framework.h>
#include <mp-units/bits/module_macros.h>
#include <mp-units/bits/sudo_cast.h>
#include <mp-units/compat_macros.h>
#include <mp-units/framework/customization_points.h>
#include <mp-units/framework/quantity_concepts.h>
#include <mp-units/framework/quantity_point_concepts.h>
@@ -75,8 +76,8 @@ concept SaneScaling = UnitConvertibleTo<MP_UNITS_REMOVE_CONST(decltype(FromU)),
* @tparam ToU a unit to use for a target quantity
*/
template<auto ToU, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
requires detail::WeakUnitOf<MP_UNITS_REMOVE_CONST(decltype(ToU)), Q::quantity_spec> &&
detail::SaneScaling<Q::unit, ToU, typename Q::rep>
requires(MP_UNITS_WEAK_UNIT_OF(MP_UNITS_REMOVE_CONST(decltype(ToU)), Q::quantity_spec)) &&
detail::SaneScaling<Q::unit, ToU, typename Q::rep>
[[nodiscard]] constexpr Quantity auto value_cast(FwdQ&& q)
{
return detail::sudo_cast<quantity<detail::make_reference(Q::quantity_spec, ToU), typename Q::rep>>(
@@ -112,18 +113,18 @@ template<typename ToRep, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
* @tparam ToRep a representation type to use for the target quantity
*/
template<Unit auto ToU, typename ToRep, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
requires detail::WeakUnitOf<MP_UNITS_REMOVE_CONST(decltype(ToU)), Q::quantity_spec> &&
RepresentationOf<ToRep, Q::quantity_spec> && std::constructible_from<ToRep, typename Q::rep> &&
detail::SaneScaling<Q::unit, ToU, ToRep>
requires(MP_UNITS_WEAK_UNIT_OF(MP_UNITS_REMOVE_CONST(decltype(ToU)), Q::quantity_spec)) &&
RepresentationOf<ToRep, Q::quantity_spec> && std::constructible_from<ToRep, typename Q::rep> &&
detail::SaneScaling<Q::unit, ToU, ToRep>
[[nodiscard]] constexpr Quantity auto value_cast(FwdQ&& q)
{
return detail::sudo_cast<quantity<detail::make_reference(Q::quantity_spec, ToU), ToRep>>(std::forward<FwdQ>(q));
}
template<typename ToRep, Unit auto ToU, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
requires detail::WeakUnitOf<MP_UNITS_REMOVE_CONST(decltype(ToU)), Q::quantity_spec> &&
RepresentationOf<ToRep, Q::quantity_spec> && std::constructible_from<ToRep, typename Q::rep> &&
detail::SaneScaling<Q::unit, ToU, ToRep>
requires(MP_UNITS_WEAK_UNIT_OF(MP_UNITS_REMOVE_CONST(decltype(ToU)), Q::quantity_spec)) &&
RepresentationOf<ToRep, Q::quantity_spec> && std::constructible_from<ToRep, typename Q::rep> &&
detail::SaneScaling<Q::unit, ToU, ToRep>
[[nodiscard]] constexpr Quantity auto value_cast(FwdQ&& q)
{
return value_cast<ToU, ToRep>(std::forward<FwdQ>(q));
@@ -146,7 +147,7 @@ template<typename ToRep, Unit auto ToU, typename FwdQ, Quantity Q = std::remove_
*/
template<Quantity ToQ, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
requires(ToQ::quantity_spec == Q::quantity_spec) &&
detail::WeakUnitOf<MP_UNITS_NONCONST_TYPE(ToQ::unit), Q::quantity_spec> &&
(MP_UNITS_WEAK_UNIT_OF(MP_UNITS_NONCONST_TYPE(ToQ::unit), Q::quantity_spec)) &&
std::constructible_from<typename ToQ::rep, typename Q::rep> &&
detail::SaneScaling<Q::unit, ToQ::unit, typename ToQ::rep>
[[nodiscard]] constexpr Quantity auto value_cast(FwdQ&& q)
@@ -165,8 +166,8 @@ template<Quantity ToQ, typename FwdQ, Quantity Q = std::remove_cvref_t<FwdQ>>
* @tparam ToU a unit to use for a target quantity point
*/
template<Unit auto ToU, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
requires detail::WeakUnitOf<MP_UNITS_REMOVE_CONST(decltype(ToU)), QP::quantity_spec> &&
detail::SaneScaling<QP::unit, ToU, typename QP::rep>
requires(MP_UNITS_WEAK_UNIT_OF(MP_UNITS_REMOVE_CONST(decltype(ToU)), QP::quantity_spec)) &&
detail::SaneScaling<QP::unit, ToU, typename QP::rep>
[[nodiscard]] constexpr QuantityPoint auto value_cast(FwdQP&& qp)
{
return quantity_point{value_cast<ToU>(std::forward<FwdQP>(qp).quantity_from_origin_is_an_implementation_detail_),
@@ -203,9 +204,9 @@ template<typename ToRep, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<
* @tparam ToRep a representation type to use for the target quantity
*/
template<Unit auto ToU, typename ToRep, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
requires detail::WeakUnitOf<MP_UNITS_REMOVE_CONST(decltype(ToU)), QP::quantity_spec> &&
RepresentationOf<ToRep, QP::quantity_spec> && std::constructible_from<ToRep, typename QP::rep> &&
detail::SaneScaling<QP::unit, ToU, ToRep>
requires(MP_UNITS_WEAK_UNIT_OF(MP_UNITS_REMOVE_CONST(decltype(ToU)), QP::quantity_spec)) &&
RepresentationOf<ToRep, QP::quantity_spec> && std::constructible_from<ToRep, typename QP::rep> &&
detail::SaneScaling<QP::unit, ToU, ToRep>
[[nodiscard]] constexpr QuantityPoint auto value_cast(FwdQP&& qp)
{
return quantity_point{
@@ -214,9 +215,9 @@ template<Unit auto ToU, typename ToRep, typename FwdQP, QuantityPoint QP = std::
}
template<typename ToRep, Unit auto ToU, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
requires detail::WeakUnitOf<MP_UNITS_REMOVE_CONST(decltype(ToU)), QP::quantity_spec> &&
RepresentationOf<ToRep, QP::quantity_spec> && std::constructible_from<ToRep, typename QP::rep> &&
detail::SaneScaling<QP::unit, ToU, ToRep>
requires(MP_UNITS_WEAK_UNIT_OF(MP_UNITS_REMOVE_CONST(decltype(ToU)), QP::quantity_spec)) &&
RepresentationOf<ToRep, QP::quantity_spec> && std::constructible_from<ToRep, typename QP::rep> &&
detail::SaneScaling<QP::unit, ToU, ToRep>
[[nodiscard]] constexpr QuantityPoint auto value_cast(FwdQP&& qp)
{
return value_cast<ToU, ToRep>(std::forward<FwdQP>(qp));
@@ -240,7 +241,7 @@ template<typename ToRep, Unit auto ToU, typename FwdQP, QuantityPoint QP = std::
*/
template<Quantity ToQ, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
requires(ToQ::quantity_spec == QP::quantity_spec) &&
detail::WeakUnitOf<MP_UNITS_NONCONST_TYPE(ToQ::unit), QP::quantity_spec> &&
(MP_UNITS_WEAK_UNIT_OF(MP_UNITS_NONCONST_TYPE(ToQ::unit), QP::quantity_spec)) &&
std::constructible_from<typename ToQ::rep, typename QP::rep> &&
detail::SaneScaling<QP::unit, ToQ::unit, typename ToQ::rep>
[[nodiscard]] constexpr QuantityPoint auto value_cast(FwdQP&& qp)
@@ -279,7 +280,7 @@ template<Quantity ToQ, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<Fw
*/
template<QuantityPoint ToQP, typename FwdQP, QuantityPoint QP = std::remove_cvref_t<FwdQP>>
requires(ToQP::quantity_spec == QP::quantity_spec) &&
detail::WeakUnitOf<MP_UNITS_NONCONST_TYPE(ToQP::unit), QP::quantity_spec> &&
(MP_UNITS_WEAK_UNIT_OF(MP_UNITS_NONCONST_TYPE(ToQP::unit), QP::quantity_spec)) &&
(detail::same_absolute_point_origins(ToQP::point_origin, QP::point_origin)) &&
std::constructible_from<typename ToQP::rep, typename QP::rep> &&
detail::SaneScaling<QP::unit, ToQP::unit, typename ToQP::rep>

View File

@@ -22,6 +22,7 @@
#pragma once
#include <mp-units/compat_macros.h>
#include <mp-units/bits/module_macros.h>
#include <mp-units/framework/customization_points.h>
#include <mp-units/framework/quantity.h>
@@ -411,11 +412,15 @@ template<Unit auto To, auto R, typename Rep>
value_cast<To>(representation_values<Rep>::one() / q);
}
{
if constexpr (AssociatedUnit<MP_UNITS_REMOVE_CONST(decltype(To))>) {
#if MP_UNITS_API_NATURAL_UNITS
if constexpr (!MP_UNITS_ASSOCIATED_UNIT<MP_UNITS_REMOVE_CONST(decltype(To))>)
return (representation_values<Rep>::one() * one).force_in(To * q.unit) / q;
else
#endif
{
constexpr QuantitySpec auto qs = get_quantity_spec(To) * quantity<R, Rep>::quantity_spec;
return qs(representation_values<Rep>::one() * one).force_in(To * q.unit) / q;
} else
return (representation_values<Rep>::one() * one).force_in(To * q.unit) / q;
}
}
/**

View File

@@ -51,13 +51,19 @@ add_mp_units_module(
include/mp-units/systems/international.h
include/mp-units/systems/isq.h
include/mp-units/systems/isq_angle.h
include/mp-units/systems/natural.h
include/mp-units/systems/si.h
include/mp-units/systems/typographic.h
include/mp-units/systems/usc.h
MODULE_INTERFACE_UNIT mp-units-systems.cpp
)
if(${projectPrefix}API_NATURAL_UNITS)
target_sources(
mp-units-systems PUBLIC FILE_SET HEADERS BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include FILES
include/mp-units/systems/natural.h
)
endif()
if(NOT ${projectPrefix}API_FREESTANDING)
target_sources(
mp-units-systems

View File

@@ -44,7 +44,9 @@ import std;
#include <mp-units/systems/international.h>
#include <mp-units/systems/isq.h>
#include <mp-units/systems/isq_angle.h>
#if MP_UNITS_API_NATURAL_UNITS
#include <mp-units/systems/natural.h>
#endif
#include <mp-units/systems/si.h>
#include <mp-units/systems/typographic.h>
#include <mp-units/systems/usc.h>

View File

@@ -48,7 +48,6 @@ add_library(
isq_angle_test.cpp
isq_test.cpp
limits_test.cpp
natural_test.cpp
prime_test.cpp
quantity_point_test.cpp
quantity_spec_test.cpp
@@ -64,6 +63,10 @@ add_library(
usc_test.cpp
)
if(${projectPrefix}API_NATURAL_UNITS)
target_sources(unit_tests_static PRIVATE natural_test.cpp)
endif()
if(NOT ${projectPrefix}API_FREESTANDING)
target_sources(unit_tests_static PRIVATE fractional_exponent_quantity.cpp math_test.cpp)
endif()

View File

@@ -20,6 +20,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#include <mp-units/compat_macros.h>
#include <mp-units/systems/isq.h>
#include <mp-units/systems/natural.h>
#include <mp-units/systems/si.h>
@@ -49,6 +50,7 @@ inline constexpr struct my_relative_origin final : relative_point_origin<my_orig
inline constexpr auto dim_speed = isq::dim_length / isq::dim_time;
#if MP_UNITS_API_NATURAL_UNITS
namespace nu {
inline constexpr struct second final : named_unit<"s"> {
} second;
@@ -56,6 +58,7 @@ inline constexpr struct hour final : named_unit<"h", mag<3600> * second> {
} hour;
} // namespace nu
#endif
// BaseDimension
static_assert(detail::BaseDimension<struct isq::dim_length>);
@@ -190,8 +193,10 @@ static_assert(Unit<struct si::standard_gravity>);
static_assert(Unit<scaled_unit<mag<10>, struct si::second>>);
static_assert(Unit<derived_unit<struct si::metre, per<struct si::second>>>);
static_assert(Unit<struct one>);
#if MP_UNITS_API_NATURAL_UNITS
static_assert(Unit<struct nu::second>);
static_assert(Unit<decltype(si::metre / nu::second)>);
#endif
static_assert(!Unit<named_unit<"?", kind_of<isq::length>>>);
static_assert(!Unit<named_unit<"?">>);
static_assert(!Unit<named_unit<"?", si::metre / si::second>>);
@@ -228,32 +233,38 @@ static_assert(!PrefixableUnit<int>);
static_assert(!PrefixableUnit<std::chrono::seconds>);
#endif
// AssociatedUnit
static_assert(AssociatedUnit<struct si::metre>);
static_assert(!AssociatedUnit<struct natural::electronvolt>);
static_assert(AssociatedUnit<MP_UNITS_NONCONST_TYPE(si::kilogram)>);
static_assert(AssociatedUnit<si::kilo_<struct si::gram>>);
static_assert(AssociatedUnit<decltype(si::metre / si::second)>);
static_assert(AssociatedUnit<decltype(inverse(si::second))>);
static_assert(AssociatedUnit<decltype(mag<10> * si::second)>);
static_assert(AssociatedUnit<decltype(square(si::metre))>);
static_assert(AssociatedUnit<decltype(pow<2>(si::metre))>);
static_assert(AssociatedUnit<struct si::standard_gravity>);
static_assert(AssociatedUnit<scaled_unit<mag<10>, struct si::second>>);
static_assert(AssociatedUnit<derived_unit<struct si::metre, per<struct si::second>>>);
static_assert(AssociatedUnit<struct one>);
static_assert(AssociatedUnit<decltype(get_common_unit(si::kilo<si::metre> / si::hour, si::metre / si::second))>);
static_assert(!AssociatedUnit<decltype(si::metre / nu::second)>);
static_assert(!AssociatedUnit<decltype(get_common_unit(si::kilo<si::metre> / nu::hour, si::metre / nu::second))>);
static_assert(!AssociatedUnit<named_unit<"?", kind_of<isq::length>>>);
static_assert(!AssociatedUnit<named_unit<"?">>);
static_assert(!AssociatedUnit<named_unit<"?", si::metre / si::second>>);
static_assert(!AssociatedUnit<named_unit<"?", si::metre, kind_of<isq::length>>>);
static_assert(!AssociatedUnit<prefixed_unit<"?", mag<10>, si::second>>);
static_assert(!AssociatedUnit<struct isq::dim_length>);
static_assert(!AssociatedUnit<int>);
// MP_UNITS_ASSOCIATED_UNIT
static_assert(MP_UNITS_ASSOCIATED_UNIT<struct si::metre>);
#if MP_UNITS_API_NATURAL_UNITS
static_assert(!MP_UNITS_ASSOCIATED_UNIT<struct natural::electronvolt>);
#endif
static_assert(MP_UNITS_ASSOCIATED_UNIT<MP_UNITS_NONCONST_TYPE(si::kilogram)>);
static_assert(MP_UNITS_ASSOCIATED_UNIT<si::kilo_<struct si::gram>>);
static_assert(MP_UNITS_ASSOCIATED_UNIT<decltype(si::metre / si::second)>);
static_assert(MP_UNITS_ASSOCIATED_UNIT<decltype(inverse(si::second))>);
static_assert(MP_UNITS_ASSOCIATED_UNIT<decltype(mag<10> * si::second)>);
static_assert(MP_UNITS_ASSOCIATED_UNIT<decltype(square(si::metre))>);
static_assert(MP_UNITS_ASSOCIATED_UNIT<decltype(pow<2>(si::metre))>);
static_assert(MP_UNITS_ASSOCIATED_UNIT<struct si::standard_gravity>);
static_assert(MP_UNITS_ASSOCIATED_UNIT<scaled_unit<mag<10>, struct si::second>>);
static_assert(MP_UNITS_ASSOCIATED_UNIT<derived_unit<struct si::metre, per<struct si::second>>>);
static_assert(MP_UNITS_ASSOCIATED_UNIT<struct one>);
static_assert(
MP_UNITS_ASSOCIATED_UNIT<decltype(get_common_unit(si::kilo<si::metre> / si::hour, si::metre / si::second))>);
#if MP_UNITS_API_NATURAL_UNITS
static_assert(!MP_UNITS_ASSOCIATED_UNIT<decltype(si::metre / nu::second)>);
static_assert(
!MP_UNITS_ASSOCIATED_UNIT<decltype(get_common_unit(si::kilo<si::metre> / nu::hour, si::metre / nu::second))>);
#endif
static_assert(!MP_UNITS_ASSOCIATED_UNIT<named_unit<"?", kind_of<isq::length>>>);
static_assert(!MP_UNITS_ASSOCIATED_UNIT<named_unit<"?">>);
static_assert(!MP_UNITS_ASSOCIATED_UNIT<named_unit<"?", si::metre / si::second>>);
static_assert(!MP_UNITS_ASSOCIATED_UNIT<named_unit<"?", si::metre, kind_of<isq::length>>>);
static_assert(!MP_UNITS_ASSOCIATED_UNIT<prefixed_unit<"?", mag<10>, si::second>>);
static_assert(!MP_UNITS_ASSOCIATED_UNIT<struct isq::dim_length>);
static_assert(!MP_UNITS_ASSOCIATED_UNIT<int>);
#if MP_UNITS_HOSTED
static_assert(!AssociatedUnit<std::chrono::seconds>);
static_assert(!MP_UNITS_ASSOCIATED_UNIT<std::chrono::seconds>);
#endif
// UnitOf

View File

@@ -69,6 +69,7 @@ inline constexpr struct metre_ final : named_unit<"m", kind_of<length>> {} metre
inline constexpr struct gram_ final : named_unit<"g", kind_of<mass>> {} gram;
inline constexpr auto kilogram = si::kilo<gram>;
#if MP_UNITS_API_NATURAL_UNITS
namespace nu {
// hypothetical natural system of units for c=1
@@ -80,6 +81,7 @@ inline constexpr struct length : system_reference<length_{}, second> {} length;
inline constexpr struct speed : system_reference<speed_{}, second / second> {} speed;
}
#endif
// derived named units
inline constexpr struct radian_ final : named_unit<"rad", metre / metre, kind_of<angular_measure>> {} radian;
@@ -218,6 +220,7 @@ static_assert(is_of_type<120.L * length[kilometre] / (2 * time[hour]),
static_assert(is_of_type<1. / 4 * area[square(metre)], decltype(1. * area[square(metre)] / 4)>);
static_assert(1. / 4 * area[square(metre)] == 1. * area[square(metre)] / 4);
#if MP_UNITS_API_NATURAL_UNITS
// Natural Units
static_assert(is_of_type<42 * nu::time[nu::second], quantity<reference<time_, nu::second_>{}, int>>);
static_assert(is_of_type<42 * nu::time[nu::minute], quantity<reference<time_, nu::minute_>{}, int>>);
@@ -251,6 +254,7 @@ static_assert(invalid_nu_unit<speed, nu::second / nu::second>);
static_assert(invalid_nu_unit<speed, nu::second / second>);
static_assert(invalid_nu_unit<mass * length / time, kilogram * nu::second / nu::second>);
static_assert(invalid_nu_unit<force, kilogram * nu::second / nu::second>);
#endif
// mixing associated units and references
static_assert(second != time[second]);

View File

@@ -53,8 +53,10 @@ inline constexpr struct gram_ final : named_unit<"g", kind_of<isq::mass>> {} gra
inline constexpr auto kilogram = kilo<gram>;
inline constexpr struct kelvin_ final : named_unit<"K", kind_of<isq::thermodynamic_temperature>> {} kelvin;
#if MP_UNITS_API_NATURAL_UNITS
// hypothetical natural units for c=1
inline constexpr struct nu_second_ final : named_unit<"s"> {} nu_second;
#endif
// derived named units
inline constexpr struct radian_ final : named_unit<"rad", metre / metre, kind_of<isq::angular_measure>> {} radian;
@@ -89,7 +91,6 @@ inline constexpr struct speed_of_light_in_vacuum_ final : named_unit<"c", mag<29
// concepts verification
static_assert(Unit<metre_>);
static_assert(Unit<second_>);
static_assert(Unit<nu_second_>);
static_assert(Unit<MP_UNITS_NONCONST_TYPE(kilogram)>);
static_assert(Unit<hertz_>);
static_assert(Unit<newton_>);
@@ -99,10 +100,13 @@ static_assert(Unit<decltype(square(metre))>);
static_assert(Unit<decltype(cubic(metre))>);
static_assert(Unit<decltype(mag<60> * second)>);
static_assert(Unit<decltype(second * second)>);
static_assert(Unit<decltype(nu_second * nu_second)>);
static_assert(Unit<decltype(metre / second)>);
static_assert(Unit<decltype(nu_second / nu_second)>);
static_assert(Unit<MP_UNITS_NONCONST_TYPE(kilometre)>);
#if MP_UNITS_API_NATURAL_UNITS
static_assert(Unit<nu_second_>);
static_assert(Unit<decltype(nu_second * nu_second)>);
static_assert(Unit<decltype(nu_second / nu_second)>);
#endif
static_assert(PrefixableUnit<metre_>);
static_assert(PrefixableUnit<hertz_>);
@@ -171,7 +175,9 @@ static_assert(get_canonical_unit(joule).mag == mag<1000>); // !!! (because of k
static_assert(joule == joule);
static_assert(joule != newton);
#if MP_UNITS_API_NATURAL_UNITS
static_assert(is_of_type<nu_second / nu_second, one_>);
#endif
// constant_unit
static_assert(is_of_type<standard_gravity, standard_gravity_>);