refactor: 💥 tag types should not expose their members

This commit is contained in:
Mateusz Pusz
2024-11-04 09:40:25 +01:00
parent 8217399a88
commit 5810420277
9 changed files with 118 additions and 119 deletions

View File

@@ -63,7 +63,7 @@ inline constexpr auto JPY = japanese_jen;
static_assert(!std::equality_comparable_with<quantity<euro, int>, quantity<us_dollar, int>>); static_assert(!std::equality_comparable_with<quantity<euro, int>, quantity<us_dollar, int>>);
#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if) #if 0 || !MP_UNITS_API_STRING_VIEW_RET // NOLINT(readability-avoid-unconditional-preprocessor-if)
// if you have only a few currencies to handle // if you have only a few currencies to handle
template<Unit auto From, Unit auto To> template<Unit auto From, Unit auto To>
@@ -77,8 +77,6 @@ template<Unit auto From, Unit auto To>
#else #else
[[nodiscard]] std::string_view to_string_view(Unit auto u) { return u.symbol.portable().c_str(); }
template<Unit auto From, Unit auto To> template<Unit auto From, Unit auto To>
[[nodiscard]] double exchange_rate(std::chrono::sys_seconds timestamp) [[nodiscard]] double exchange_rate(std::chrono::sys_seconds timestamp)
{ {
@@ -88,7 +86,7 @@ template<Unit auto From, Unit auto To>
// ... // ...
}; };
return rates.at(std::make_pair(to_string_view(From), to_string_view(To))); return rates.at(std::make_pair(unit_symbol(From), unit_symbol(To)));
} }
#endif #endif

View File

@@ -51,10 +51,10 @@ template<typename... Nums, typename... Dens>
template<AssociatedUnit U> template<AssociatedUnit U>
[[nodiscard]] consteval auto all_are_kinds(U) [[nodiscard]] consteval auto all_are_kinds(U)
{ {
if constexpr (requires { U::quantity_spec; }) if constexpr (requires { U::_quantity_spec_; })
return QuantityKindSpec<std::remove_const_t<decltype(U::quantity_spec)>>; return QuantityKindSpec<std::remove_const_t<decltype(U::_quantity_spec_)>>;
else if constexpr (requires { U::reference_unit; }) else if constexpr (requires { U::_reference_unit_; })
return all_are_kinds(U::reference_unit); return all_are_kinds(U::_reference_unit_);
else if constexpr (requires { typename U::_num_; }) { else if constexpr (requires { typename U::_num_; }) {
return all_are_kinds(typename U::_num_{}, typename U::_den_{}); return all_are_kinds(typename U::_num_{}, typename U::_den_{});
} }
@@ -75,10 +75,10 @@ template<typename... Us>
template<AssociatedUnit U> template<AssociatedUnit U>
[[nodiscard]] consteval auto get_associated_quantity_impl(U u) [[nodiscard]] consteval auto get_associated_quantity_impl(U u)
{ {
if constexpr (requires { U::quantity_spec; }) if constexpr (requires { U::_quantity_spec_; })
return remove_kind(U::quantity_spec); return remove_kind(U::_quantity_spec_);
else if constexpr (requires { U::reference_unit; }) else if constexpr (requires { U::_reference_unit_; })
return get_associated_quantity_impl(U::reference_unit); return get_associated_quantity_impl(U::_reference_unit_);
else if constexpr (requires { typename U::_num_; }) { else if constexpr (requires { typename U::_num_; }) {
return expr_map<to_quantity_spec, derived_quantity_spec, struct dimensionless, type_list_of_quantity_spec_less>(u); return expr_map<to_quantity_spec, derived_quantity_spec, struct dimensionless, type_list_of_quantity_spec_less>(u);
} }

View File

@@ -120,7 +120,7 @@ struct dimension_interface {
*/ */
MP_UNITS_EXPORT template<symbol_text Symbol> MP_UNITS_EXPORT template<symbol_text Symbol>
struct base_dimension : detail::dimension_interface { struct base_dimension : detail::dimension_interface {
static constexpr auto symbol = Symbol; ///< Unique base dimension identifier static constexpr auto _symbol_ = Symbol; ///< Unique base dimension identifier
}; };
/** /**
@@ -229,10 +229,10 @@ MP_UNITS_EXPORT_END
namespace detail { namespace detail {
template<typename CharT, std::output_iterator<CharT> Out, Dimension D> template<typename CharT, std::output_iterator<CharT> Out, Dimension D>
requires requires { D::symbol; } requires requires { D::_symbol_; }
constexpr Out dimension_symbol_impl(Out out, D, const dimension_symbol_formatting& fmt, bool negative_power) constexpr Out dimension_symbol_impl(Out out, D, const dimension_symbol_formatting& fmt, bool negative_power)
{ {
return copy_symbol<CharT>(D::symbol, fmt.encoding, negative_power, out); return copy_symbol<CharT>(D::_symbol_, fmt.encoding, negative_power, out);
} }
template<typename CharT, std::output_iterator<CharT> Out, typename F, int Num, int... Den> template<typename CharT, std::output_iterator<CharT> Out, typename F, int Num, int... Den>

View File

@@ -52,14 +52,14 @@ template<PointOrigin PO>
} }
struct point_origin_interface { struct point_origin_interface {
template<PointOrigin PO, typename FwdQ, QuantityOf<PO::quantity_spec> Q = std::remove_cvref_t<FwdQ>> template<PointOrigin PO, typename FwdQ, QuantityOf<PO::_quantity_spec_> Q = std::remove_cvref_t<FwdQ>>
[[nodiscard]] friend constexpr quantity_point<Q::reference, MP_UNITS_EXPRESSION_WORKAROUND(PO{}), typename Q::rep> [[nodiscard]] friend constexpr quantity_point<Q::reference, MP_UNITS_EXPRESSION_WORKAROUND(PO{}), typename Q::rep>
operator+(PO, FwdQ&& q) operator+(PO, FwdQ&& q)
{ {
return quantity_point{std::forward<FwdQ>(q), PO{}}; return quantity_point{std::forward<FwdQ>(q), PO{}};
} }
template<Quantity FwdQ, PointOrigin PO, QuantityOf<PO::quantity_spec> Q = std::remove_cvref_t<FwdQ>> template<Quantity FwdQ, PointOrigin PO, QuantityOf<PO::_quantity_spec_> Q = std::remove_cvref_t<FwdQ>>
[[nodiscard]] friend constexpr quantity_point<Q::reference, MP_UNITS_EXPRESSION_WORKAROUND(PO{}), typename Q::rep> [[nodiscard]] friend constexpr quantity_point<Q::reference, MP_UNITS_EXPRESSION_WORKAROUND(PO{}), typename Q::rep>
operator+(FwdQ&& q, PO po) operator+(FwdQ&& q, PO po)
{ {
@@ -67,7 +67,7 @@ struct point_origin_interface {
} }
template<PointOrigin PO, Quantity Q> template<PointOrigin PO, Quantity Q>
requires ReferenceOf<std::remove_const_t<decltype(Q::reference)>, PO::quantity_spec> requires ReferenceOf<std::remove_const_t<decltype(Q::reference)>, PO::_quantity_spec_>
[[nodiscard]] friend constexpr QuantityPoint auto operator-(PO po, const Q& q) [[nodiscard]] friend constexpr QuantityPoint auto operator-(PO po, const Q& q)
requires requires { -q; } requires requires { -q; }
{ {
@@ -75,17 +75,17 @@ struct point_origin_interface {
} }
template<PointOrigin PO1, detail::SameAbsolutePointOriginAs<PO1{}> PO2> template<PointOrigin PO1, detail::SameAbsolutePointOriginAs<PO1{}> PO2>
requires QuantitySpecOf<std::remove_const_t<decltype(PO1::quantity_spec)>, PO2::quantity_spec> && requires QuantitySpecOf<std::remove_const_t<decltype(PO1::_quantity_spec_)>, PO2::_quantity_spec_> &&
(is_derived_from_specialization_of_v<PO1, relative_point_origin> || (is_derived_from_specialization_of_v<PO1, relative_point_origin> ||
is_derived_from_specialization_of_v<PO2, relative_point_origin>) is_derived_from_specialization_of_v<PO2, relative_point_origin>)
[[nodiscard]] friend constexpr Quantity auto operator-(PO1 po1, PO2 po2) [[nodiscard]] friend constexpr Quantity auto operator-(PO1 po1, PO2 po2)
{ {
if constexpr (is_derived_from_specialization_of_v<PO1, absolute_point_origin>) { if constexpr (is_derived_from_specialization_of_v<PO1, absolute_point_origin>) {
return po1 - po2.quantity_point; return po1 - po2._quantity_point_;
} else if constexpr (is_derived_from_specialization_of_v<PO2, absolute_point_origin>) { } else if constexpr (is_derived_from_specialization_of_v<PO2, absolute_point_origin>) {
return po1.quantity_point - po2; return po1._quantity_point_ - po2;
} else { } else {
return po1.quantity_point - po2.quantity_point; return po1._quantity_point_ - po2._quantity_point_;
} }
} }
@@ -95,14 +95,14 @@ struct point_origin_interface {
if constexpr (is_derived_from_specialization_of_v<PO1, absolute_point_origin> && if constexpr (is_derived_from_specialization_of_v<PO1, absolute_point_origin> &&
is_derived_from_specialization_of_v<PO2, absolute_point_origin>) is_derived_from_specialization_of_v<PO2, absolute_point_origin>)
return is_same_v<PO1, PO2> || (detail::is_zeroth_point_origin(po1) && detail::is_zeroth_point_origin(po2) && return is_same_v<PO1, PO2> || (detail::is_zeroth_point_origin(po1) && detail::is_zeroth_point_origin(po2) &&
interconvertible(po1.quantity_spec, po2.quantity_spec)); interconvertible(po1._quantity_spec_, po2._quantity_spec_));
else if constexpr (is_derived_from_specialization_of_v<PO1, relative_point_origin> && else if constexpr (is_derived_from_specialization_of_v<PO1, relative_point_origin> &&
is_derived_from_specialization_of_v<PO2, relative_point_origin>) is_derived_from_specialization_of_v<PO2, relative_point_origin>)
return PO1::quantity_point == PO2::quantity_point; return PO1::_quantity_point_ == PO2::_quantity_point_;
else if constexpr (is_derived_from_specialization_of_v<PO1, relative_point_origin>) else if constexpr (is_derived_from_specialization_of_v<PO1, relative_point_origin>)
return detail::same_absolute_point_origins(po1, po2) && is_eq_zero(PO1::quantity_point.quantity_from_zero()); return detail::same_absolute_point_origins(po1, po2) && is_eq_zero(PO1::_quantity_point_.quantity_from_zero());
else if constexpr (is_derived_from_specialization_of_v<PO2, relative_point_origin>) else if constexpr (is_derived_from_specialization_of_v<PO2, relative_point_origin>)
return detail::same_absolute_point_origins(po1, po2) && is_eq_zero(PO2::quantity_point.quantity_from_zero()); return detail::same_absolute_point_origins(po1, po2) && is_eq_zero(PO2::_quantity_point_.quantity_from_zero());
} }
}; };
@@ -110,20 +110,20 @@ struct point_origin_interface {
MP_UNITS_EXPORT template<QuantitySpec auto QS> MP_UNITS_EXPORT template<QuantitySpec auto QS>
struct absolute_point_origin : detail::point_origin_interface { struct absolute_point_origin : detail::point_origin_interface {
static constexpr QuantitySpec auto quantity_spec = QS; static constexpr QuantitySpec auto _quantity_spec_ = QS;
}; };
MP_UNITS_EXPORT template<QuantityPoint auto QP> MP_UNITS_EXPORT template<QuantityPoint auto QP>
struct relative_point_origin : detail::point_origin_interface { struct relative_point_origin : detail::point_origin_interface {
static constexpr QuantityPoint auto quantity_point = QP; static constexpr QuantityPoint auto _quantity_point_ = QP;
static constexpr QuantitySpec auto quantity_spec = []() { static constexpr QuantitySpec auto _quantity_spec_ = []() {
// select the strongest of specs // select the strongest of specs
if constexpr (detail::QuantityKindSpec<std::remove_const_t<decltype(QP.quantity_spec)>>) if constexpr (detail::QuantityKindSpec<std::remove_const_t<decltype(QP.quantity_spec)>>)
return QP.point_origin.quantity_spec; return QP.point_origin._quantity_spec_;
else else
return QP.quantity_spec; return QP.quantity_spec;
}(); }();
static constexpr PointOrigin auto absolute_point_origin = QP.absolute_point_origin; static constexpr PointOrigin auto _absolute_point_origin_ = QP.absolute_point_origin;
}; };
template<QuantitySpec auto QS> template<QuantitySpec auto QS>
@@ -143,8 +143,8 @@ constexpr bool is_specialization_of_zeroth_point_origin<zeroth_point_origin_<QS>
MP_UNITS_EXPORT template<Reference R> MP_UNITS_EXPORT template<Reference R>
[[nodiscard]] consteval PointOriginFor<get_quantity_spec(R{})> auto default_point_origin(R) [[nodiscard]] consteval PointOriginFor<get_quantity_spec(R{})> auto default_point_origin(R)
{ {
if constexpr (requires { get_unit(R{}).point_origin; }) if constexpr (requires { get_unit(R{})._point_origin_; })
return get_unit(R{}).point_origin; return get_unit(R{})._point_origin_;
else else
return zeroth_point_origin<get_quantity_spec(R{})>; return zeroth_point_origin<get_quantity_spec(R{})>;
} }
@@ -157,7 +157,7 @@ template<PointOrigin PO>
if constexpr (is_derived_from_specialization_of_v<PO, absolute_point_origin>) if constexpr (is_derived_from_specialization_of_v<PO, absolute_point_origin>)
return po; return po;
else else
return po.quantity_point.absolute_point_origin; return po._quantity_point_.absolute_point_origin;
} }
} // namespace detail } // namespace detail
@@ -220,7 +220,7 @@ public:
{ {
} }
template<typename FwdQ, PointOrigin PO2, QuantityOf<PO2::quantity_spec> Q = std::remove_cvref_t<FwdQ>> template<typename FwdQ, PointOrigin PO2, QuantityOf<PO2::_quantity_spec_> Q = std::remove_cvref_t<FwdQ>>
requires std::constructible_from<quantity_type, FwdQ> && detail::SameAbsolutePointOriginAs<PO2, PO> requires std::constructible_from<quantity_type, FwdQ> && detail::SameAbsolutePointOriginAs<PO2, PO>
constexpr quantity_point(FwdQ&& q, PO2) : constexpr quantity_point(FwdQ&& q, PO2) :
quantity_point( quantity_point(
@@ -309,9 +309,9 @@ public:
[[nodiscard]] constexpr Quantity auto quantity_from_zero() const [[nodiscard]] constexpr Quantity auto quantity_from_zero() const
{ {
if constexpr (requires { unit.point_origin; }) { if constexpr (requires { unit._point_origin_; }) {
// original quantity point unit can be lost in the below operation // original quantity point unit can be lost in the below operation
const auto q = quantity_from(unit.point_origin); const auto q = quantity_from(unit._point_origin_);
if constexpr (requires { q.in(unit); }) if constexpr (requires { q.in(unit); })
// restore the unit if possible (non-truncating) // restore the unit if possible (non-truncating)
return q.in(unit); return q.in(unit);
@@ -452,7 +452,7 @@ public:
// binary operators on quantity points // binary operators on quantity points
template<std::derived_from<quantity_point> QP, auto R2, typename Rep2> template<std::derived_from<quantity_point> QP, auto R2, typename Rep2>
// TODO simplify when gcc catches up // TODO simplify when gcc catches up
requires ReferenceOf<MP_UNITS_REMOVE_CONST(decltype(R2)), PO.quantity_spec> requires ReferenceOf<MP_UNITS_REMOVE_CONST(decltype(R2)), PO._quantity_spec_>
[[nodiscard]] friend constexpr QuantityPoint auto operator+(const QP& qp, const quantity<R2, Rep2>& q) [[nodiscard]] friend constexpr QuantityPoint auto operator+(const QP& qp, const quantity<R2, Rep2>& q)
requires requires { qp.quantity_ref_from(PO) + q; } requires requires { qp.quantity_ref_from(PO) + q; }
{ {
@@ -464,7 +464,7 @@ public:
template<auto R1, typename Rep1, std::derived_from<quantity_point> QP> template<auto R1, typename Rep1, std::derived_from<quantity_point> QP>
// TODO simplify when gcc catches up // TODO simplify when gcc catches up
requires ReferenceOf<MP_UNITS_REMOVE_CONST(decltype(R1)), PO.quantity_spec> requires ReferenceOf<MP_UNITS_REMOVE_CONST(decltype(R1)), PO._quantity_spec_>
[[nodiscard]] friend constexpr QuantityPoint auto operator+(const quantity<R1, Rep1>& q, const QP& qp) [[nodiscard]] friend constexpr QuantityPoint auto operator+(const quantity<R1, Rep1>& q, const QP& qp)
requires requires { q + qp.quantity_ref_from(PO); } requires requires { q + qp.quantity_ref_from(PO); }
{ {
@@ -473,7 +473,7 @@ public:
template<std::derived_from<quantity_point> QP, auto R2, typename Rep2> template<std::derived_from<quantity_point> QP, auto R2, typename Rep2>
// TODO simplify when gcc catches up // TODO simplify when gcc catches up
requires ReferenceOf<MP_UNITS_REMOVE_CONST(decltype(R2)), PO.quantity_spec> requires ReferenceOf<MP_UNITS_REMOVE_CONST(decltype(R2)), PO._quantity_spec_>
[[nodiscard]] friend constexpr QuantityPoint auto operator-(const QP& qp, const quantity<R2, Rep2>& q) [[nodiscard]] friend constexpr QuantityPoint auto operator-(const QP& qp, const quantity<R2, Rep2>& q)
requires requires { qp.quantity_ref_from(PO) - q; } requires requires { qp.quantity_ref_from(PO) - q; }
{ {
@@ -497,7 +497,7 @@ public:
template<std::derived_from<quantity_point> QP, PointOrigin PO2> template<std::derived_from<quantity_point> QP, PointOrigin PO2>
requires QuantityPointOf<quantity_point, PO2{}> && requires QuantityPointOf<quantity_point, PO2{}> &&
ReferenceOf<std::remove_const_t<decltype(reference)>, PO2::quantity_spec> ReferenceOf<std::remove_const_t<decltype(reference)>, PO2::_quantity_spec_>
[[nodiscard]] friend constexpr Quantity auto operator-(const QP& qp, PO2 po) [[nodiscard]] friend constexpr Quantity auto operator-(const QP& qp, PO2 po)
{ {
if constexpr (point_origin == po) if constexpr (point_origin == po)
@@ -508,18 +508,19 @@ public:
else else
return qp.quantity_ref_from(point_origin) + (qp.point_origin - qp.absolute_point_origin); return qp.quantity_ref_from(point_origin) + (qp.point_origin - qp.absolute_point_origin);
} else { } else {
if constexpr (point_origin == po.quantity_point.point_origin) if constexpr (point_origin == po._quantity_point_.point_origin)
return qp.quantity_ref_from(point_origin) - po.quantity_point.quantity_ref_from(po.quantity_point.point_origin); return qp.quantity_ref_from(point_origin) -
po._quantity_point_.quantity_ref_from(po._quantity_point_.point_origin);
else else
return qp.quantity_ref_from(point_origin) - return qp.quantity_ref_from(point_origin) -
po.quantity_point.quantity_ref_from(po.quantity_point.point_origin) + po._quantity_point_.quantity_ref_from(po._quantity_point_.point_origin) +
(qp.point_origin - po.quantity_point.point_origin); (qp.point_origin - po._quantity_point_.point_origin);
} }
} }
template<PointOrigin PO1, std::derived_from<quantity_point> QP> template<PointOrigin PO1, std::derived_from<quantity_point> QP>
requires QuantityPointOf<quantity_point, PO1{}> && requires QuantityPointOf<quantity_point, PO1{}> &&
ReferenceOf<std::remove_const_t<decltype(reference)>, PO1::quantity_spec> ReferenceOf<std::remove_const_t<decltype(reference)>, PO1::_quantity_spec_>
[[nodiscard]] friend constexpr Quantity auto operator-(PO1 po, const QP& qp) [[nodiscard]] friend constexpr Quantity auto operator-(PO1 po, const QP& qp)
{ {
return -(qp - po); return -(qp - po);

View File

@@ -73,7 +73,7 @@ concept PointOrigin = detail::TagType<T> && std::derived_from<T, detail::point_o
* Satisfied by all quantity point origins that are defined using a provided quantity specification. * Satisfied by all quantity point origins that are defined using a provided quantity specification.
*/ */
MP_UNITS_EXPORT template<typename T, auto QS> MP_UNITS_EXPORT template<typename T, auto QS>
concept PointOriginFor = PointOrigin<T> && QuantitySpecOf<MP_UNITS_REMOVE_CONST(decltype(QS)), T::quantity_spec>; concept PointOriginFor = PointOrigin<T> && QuantitySpecOf<MP_UNITS_REMOVE_CONST(decltype(QS)), T::_quantity_spec_>;
MP_UNITS_EXPORT template<Reference auto R, PointOriginFor<get_quantity_spec(R)> auto PO, MP_UNITS_EXPORT template<Reference auto R, PointOriginFor<get_quantity_spec(R)> auto PO,
RepresentationOf<get_quantity_spec(R).character> Rep> RepresentationOf<get_quantity_spec(R).character> Rep>
@@ -100,11 +100,11 @@ template<PointOrigin PO1, PointOrigin PO2>
return po1 == po2; return po1 == po2;
else if constexpr (is_derived_from_specialization_of_v<PO1, relative_point_origin> && else if constexpr (is_derived_from_specialization_of_v<PO1, relative_point_origin> &&
is_derived_from_specialization_of_v<PO2, relative_point_origin>) is_derived_from_specialization_of_v<PO2, relative_point_origin>)
return po1.absolute_point_origin == po2.absolute_point_origin; return po1._absolute_point_origin_ == po2._absolute_point_origin_;
else if constexpr (is_derived_from_specialization_of_v<PO1, relative_point_origin>) else if constexpr (is_derived_from_specialization_of_v<PO1, relative_point_origin>)
return po1.absolute_point_origin == po2; return po1._absolute_point_origin_ == po2;
else if constexpr (is_derived_from_specialization_of_v<PO2, relative_point_origin>) else if constexpr (is_derived_from_specialization_of_v<PO2, relative_point_origin>)
return po1 == po2.absolute_point_origin; return po1 == po2._absolute_point_origin_;
else else
return false; return false;
} }

View File

@@ -161,10 +161,10 @@ struct unit_interface {
if constexpr (std::is_same_v<M, std::remove_const_t<decltype(mp_units::mag<1>)>>) if constexpr (std::is_same_v<M, std::remove_const_t<decltype(mp_units::mag<1>)>>)
return u; return u;
else if constexpr (is_specialization_of_scaled_unit<U>) { else if constexpr (is_specialization_of_scaled_unit<U>) {
if constexpr (M{} * U::mag == mag<1>) if constexpr (M{} * U::_mag_ == mag<1>)
return U::reference_unit; return U::_reference_unit_;
else else
return scaled_unit<M{} * U::mag, std::remove_const_t<decltype(U::reference_unit)>>{}; return scaled_unit<M{} * U::_mag_, std::remove_const_t<decltype(U::_reference_unit_)>>{};
} else } else
return scaled_unit<M{}, U>{}; return scaled_unit<M{}, U>{};
} }
@@ -221,19 +221,19 @@ struct unit_interface {
} }
}; };
template<Unit U, bool = requires { U::point_origin; }> template<Unit U, bool = requires { U::_point_origin_; }>
struct propagate_point_origin {}; struct propagate_point_origin {};
template<Unit U> template<Unit U>
struct propagate_point_origin<U, true> { struct propagate_point_origin<U, true> {
static constexpr auto point_origin = U::point_origin; static constexpr auto _point_origin_ = U::_point_origin_;
}; };
template<Magnitude auto M, Unit U> template<Magnitude auto M, Unit U>
struct scaled_unit_impl : detail::unit_interface, detail::propagate_point_origin<U> { struct scaled_unit_impl : detail::unit_interface, detail::propagate_point_origin<U> {
using _base_type_ = scaled_unit_impl; // exposition only using _base_type_ = scaled_unit_impl; // exposition only
static constexpr Magnitude auto mag = M; static constexpr Magnitude auto _mag_ = M;
static constexpr U reference_unit{}; static constexpr U _reference_unit_{};
}; };
} // namespace detail } // namespace detail
@@ -307,17 +307,17 @@ template<symbol_text Symbol, detail::QuantityKindSpec auto QS>
requires(!Symbol.empty()) && detail::BaseDimension<std::remove_const_t<decltype(QS.dimension)>> requires(!Symbol.empty()) && detail::BaseDimension<std::remove_const_t<decltype(QS.dimension)>>
struct named_unit<Symbol, QS> : detail::unit_interface { struct named_unit<Symbol, QS> : detail::unit_interface {
using _base_type_ = named_unit; // exposition only using _base_type_ = named_unit; // exposition only
static constexpr auto symbol = Symbol; ///< Unique base unit identifier static constexpr auto _symbol_ = Symbol; ///< Unique base unit identifier
static constexpr auto quantity_spec = QS; static constexpr auto _quantity_spec_ = QS;
}; };
template<symbol_text Symbol, detail::QuantityKindSpec auto QS, PointOrigin auto PO> template<symbol_text Symbol, detail::QuantityKindSpec auto QS, PointOrigin auto PO>
requires(!Symbol.empty()) && detail::BaseDimension<std::remove_const_t<decltype(QS.dimension)>> requires(!Symbol.empty()) && detail::BaseDimension<std::remove_const_t<decltype(QS.dimension)>>
struct named_unit<Symbol, QS, PO> : detail::unit_interface { struct named_unit<Symbol, QS, PO> : detail::unit_interface {
using _base_type_ = named_unit; // exposition only using _base_type_ = named_unit; // exposition only
static constexpr auto symbol = Symbol; ///< Unique base unit identifier static constexpr auto _symbol_ = Symbol; ///< Unique base unit identifier
static constexpr auto quantity_spec = QS; static constexpr auto _quantity_spec_ = QS;
static constexpr auto point_origin = PO; static constexpr auto _point_origin_ = PO;
}; };
/** /**
@@ -334,7 +334,7 @@ template<symbol_text Symbol>
requires(!Symbol.empty()) requires(!Symbol.empty())
struct named_unit<Symbol> : detail::unit_interface { struct named_unit<Symbol> : detail::unit_interface {
using _base_type_ = named_unit; // exposition only using _base_type_ = named_unit; // exposition only
static constexpr auto symbol = Symbol; ///< Unique base unit identifier static constexpr auto _symbol_ = Symbol; ///< Unique base unit identifier
}; };
/** /**
@@ -349,15 +349,15 @@ template<symbol_text Symbol, Unit auto U>
requires(!Symbol.empty()) requires(!Symbol.empty())
struct named_unit<Symbol, U> : decltype(U)::_base_type_ { struct named_unit<Symbol, U> : decltype(U)::_base_type_ {
using _base_type_ = named_unit; // exposition only using _base_type_ = named_unit; // exposition only
static constexpr auto symbol = Symbol; ///< Unique unit identifier static constexpr auto _symbol_ = Symbol; ///< Unique unit identifier
}; };
template<symbol_text Symbol, Unit auto U, PointOrigin auto PO> template<symbol_text Symbol, Unit auto U, PointOrigin auto PO>
requires(!Symbol.empty()) requires(!Symbol.empty())
struct named_unit<Symbol, U, PO> : decltype(U)::_base_type_ { struct named_unit<Symbol, U, PO> : decltype(U)::_base_type_ {
using _base_type_ = named_unit; // exposition only using _base_type_ = named_unit; // exposition only
static constexpr auto symbol = Symbol; ///< Unique unit identifier static constexpr auto _symbol_ = Symbol; ///< Unique unit identifier
static constexpr auto point_origin = PO; static constexpr auto _point_origin_ = PO;
}; };
/** /**
@@ -373,17 +373,17 @@ template<symbol_text Symbol, AssociatedUnit auto U, detail::QuantityKindSpec aut
requires(!Symbol.empty()) && (QS.dimension == detail::get_associated_quantity(U).dimension) requires(!Symbol.empty()) && (QS.dimension == detail::get_associated_quantity(U).dimension)
struct named_unit<Symbol, U, QS> : decltype(U)::_base_type_ { struct named_unit<Symbol, U, QS> : decltype(U)::_base_type_ {
using _base_type_ = named_unit; // exposition only using _base_type_ = named_unit; // exposition only
static constexpr auto symbol = Symbol; ///< Unique unit identifier static constexpr auto _symbol_ = Symbol; ///< Unique unit identifier
static constexpr auto quantity_spec = QS; static constexpr auto _quantity_spec_ = QS;
}; };
template<symbol_text Symbol, AssociatedUnit auto U, detail::QuantityKindSpec auto QS, PointOrigin auto PO> template<symbol_text Symbol, AssociatedUnit auto U, detail::QuantityKindSpec auto QS, PointOrigin auto PO>
requires(!Symbol.empty()) && (QS.dimension == detail::get_associated_quantity(U).dimension) requires(!Symbol.empty()) && (QS.dimension == detail::get_associated_quantity(U).dimension)
struct named_unit<Symbol, U, QS, PO> : decltype(U)::_base_type_ { struct named_unit<Symbol, U, QS, PO> : decltype(U)::_base_type_ {
using _base_type_ = named_unit; // exposition only using _base_type_ = named_unit; // exposition only
static constexpr auto symbol = Symbol; ///< Unique unit identifier static constexpr auto _symbol_ = Symbol; ///< Unique unit identifier
static constexpr auto quantity_spec = QS; static constexpr auto _quantity_spec_ = QS;
static constexpr auto point_origin = PO; static constexpr auto _point_origin_ = PO;
}; };
/** /**
@@ -412,7 +412,7 @@ MP_UNITS_EXPORT template<symbol_text Symbol, Magnitude auto M, PrefixableUnit au
requires(!Symbol.empty()) requires(!Symbol.empty())
struct prefixed_unit : decltype(M * U)::_base_type_ { struct prefixed_unit : decltype(M * U)::_base_type_ {
using _base_type_ = prefixed_unit; // exposition only using _base_type_ = prefixed_unit; // exposition only
static constexpr auto symbol = Symbol + U.symbol; static constexpr auto _symbol_ = Symbol + U._symbol_;
}; };
namespace detail { namespace detail {
@@ -765,10 +765,10 @@ MP_UNITS_EXPORT_END
namespace detail { namespace detail {
template<typename CharT, std::output_iterator<CharT> Out, Unit U> template<typename CharT, std::output_iterator<CharT> Out, Unit U>
requires requires { U::symbol; } requires requires { U::_symbol_; }
constexpr Out unit_symbol_impl(Out out, U, const unit_symbol_formatting& fmt, bool negative_power) constexpr Out unit_symbol_impl(Out out, U, const unit_symbol_formatting& fmt, bool negative_power)
{ {
return copy_symbol<CharT>(U::symbol, fmt.encoding, negative_power, out); return copy_symbol<CharT>(U::_symbol_, fmt.encoding, negative_power, out);
} }
template<typename CharT, std::output_iterator<CharT> Out, auto M, typename U> template<typename CharT, std::output_iterator<CharT> Out, auto M, typename U>
@@ -777,8 +777,8 @@ constexpr Out unit_symbol_impl(Out out, const scaled_unit_impl<M, U>& u, const u
{ {
*out++ = '['; *out++ = '[';
_magnitude_symbol<CharT>(out, M, fmt); _magnitude_symbol<CharT>(out, M, fmt);
if constexpr (space_before_unit_symbol<scaled_unit<M, U>::reference_unit>) *out++ = ' '; if constexpr (space_before_unit_symbol<scaled_unit<M, U>::_reference_unit_>) *out++ = ' ';
unit_symbol_impl<CharT>(out, u.reference_unit, fmt, negative_power); unit_symbol_impl<CharT>(out, u._reference_unit_, fmt, negative_power);
*out++ = ']'; *out++ = ']';
return out; return out;
} }
@@ -787,8 +787,8 @@ template<typename... Us, Unit U>
[[nodiscard]] consteval Unit auto get_common_unit_in(common_unit<Us...>, U u) [[nodiscard]] consteval Unit auto get_common_unit_in(common_unit<Us...>, U u)
{ {
auto get_magnitude = [&]() { auto get_magnitude = [&]() {
if constexpr (requires { common_unit<Us...>::mag; }) if constexpr (requires { common_unit<Us...>::_mag_; })
return common_unit<Us...>::mag; return common_unit<Us...>::_mag_;
else else
return mag<1>; return mag<1>;
}; };

View File

@@ -80,9 +80,9 @@ template<typename... Us>
template<Unit U> template<Unit U>
[[nodiscard]] consteval bool has_associated_quantity(U) [[nodiscard]] consteval bool has_associated_quantity(U)
{ {
if constexpr (requires { U::quantity_spec; }) return true; if constexpr (requires { U::_quantity_spec_; }) return true;
if constexpr (requires { U::reference_unit; }) if constexpr (requires { U::_reference_unit_; })
return has_associated_quantity(U::reference_unit); return has_associated_quantity(U::_reference_unit_);
else if constexpr (requires { typename U::_num_; }) else if constexpr (requires { typename U::_num_; })
return has_associated_quantity(typename U::_num_{}) && has_associated_quantity(typename U::_den_{}); return has_associated_quantity(typename U::_num_{}) && has_associated_quantity(typename U::_den_{});
else else
@@ -131,7 +131,7 @@ concept UnitCompatibleWith =
(!AssociatedUnit<U> || UnitOf<U, QS>) && detail::UnitConvertibleTo<FromU, U{}>; (!AssociatedUnit<U> || UnitOf<U, QS>) && detail::UnitConvertibleTo<FromU, U{}>;
template<typename T> template<typename T>
concept OffsetUnit = Unit<T> && requires { T::point_origin; }; concept OffsetUnit = Unit<T> && requires { T::_point_origin_; };
} // namespace detail } // namespace detail

View File

@@ -118,9 +118,9 @@ struct relative_po_ final : relative_point_origin<QP> {};
template<auto QP> template<auto QP>
constexpr relative_po_<QP> relative_po; constexpr relative_po_<QP> relative_po;
static_assert(relative_po<absolute_po<isq::length> + isq::height(42 * m)>.quantity_spec == isq::height); static_assert(relative_po<absolute_po<isq::length> + isq::height(42 * m)>._quantity_spec_ == isq::height);
static_assert(relative_po<absolute_po<kind_of<isq::length>> + isq::height(42 * m)>.quantity_spec == isq::height); static_assert(relative_po<absolute_po<kind_of<isq::length>> + isq::height(42 * m)>._quantity_spec_ == isq::height);
static_assert(relative_po<absolute_po<isq::height> + 42 * m>.quantity_spec == isq::height); static_assert(relative_po<absolute_po<isq::height> + 42 * m>._quantity_spec_ == isq::height);
inline constexpr struct my_kelvin final : named_unit<"my_K", mag<10> * si::kelvin> { inline constexpr struct my_kelvin final : named_unit<"my_K", mag<10> * si::kelvin> {
} my_kelvin; } my_kelvin;

View File

@@ -191,7 +191,7 @@ static_assert(convertible(standard_gravity, standard_gravity));
static_assert(convertible(standard_gravity, metre / square(second))); static_assert(convertible(standard_gravity, metre / square(second)));
static_assert(standard_gravity == standard_gravity); static_assert(standard_gravity == standard_gravity);
static_assert(standard_gravity != metre / square(second)); // magnitude is different static_assert(standard_gravity != metre / square(second)); // magnitude is different
static_assert(standard_gravity.symbol == symbol_text{u8"g₀", "g_0"}); static_assert(standard_gravity._symbol_ == symbol_text{u8"g₀", "g_0"});
// prefixed_unit // prefixed_unit
static_assert(is_of_type<kilometre, std::remove_const_t<decltype(kilo<metre>)>>); static_assert(is_of_type<kilometre, std::remove_const_t<decltype(kilo<metre>)>>);
@@ -199,7 +199,7 @@ static_assert(is_of_type<get_canonical_unit(kilometre).reference_unit, metre_>);
static_assert(get_canonical_unit(kilometre).mag == mag<1000>); static_assert(get_canonical_unit(kilometre).mag == mag<1000>);
static_assert(convertible(kilometre, metre)); static_assert(convertible(kilometre, metre));
static_assert(kilometre != metre); static_assert(kilometre != metre);
static_assert(kilometre.symbol == "km"); static_assert(kilometre._symbol_ == "km");
static_assert(is_of_type<kilojoule, std::remove_const_t<decltype(kilo<joule>)>>); static_assert(is_of_type<kilojoule, std::remove_const_t<decltype(kilo<joule>)>>);
static_assert(is_of_type<get_canonical_unit(kilojoule).reference_unit, static_assert(is_of_type<get_canonical_unit(kilojoule).reference_unit,
@@ -207,7 +207,7 @@ static_assert(is_of_type<get_canonical_unit(kilojoule).reference_unit,
static_assert(get_canonical_unit(kilojoule).mag == mag<1'000'000>); static_assert(get_canonical_unit(kilojoule).mag == mag<1'000'000>);
static_assert(convertible(kilojoule, joule)); static_assert(convertible(kilojoule, joule));
static_assert(kilojoule != joule); static_assert(kilojoule != joule);
static_assert(kilojoule.symbol == "kJ"); static_assert(kilojoule._symbol_ == "kJ");
static_assert(is_of_type<kilo<metre>, kilo_<metre_>>); static_assert(is_of_type<kilo<metre>, kilo_<metre_>>);
static_assert(is_of_type<kilo<joule>, kilo_<joule_>>); static_assert(is_of_type<kilo<joule>, kilo_<joule_>>);
@@ -217,30 +217,30 @@ static_assert(
// prefixes // prefixes
static_assert(si::quecto<metre>.symbol == "qm"); static_assert(si::quecto<metre>._symbol_ == "qm");
static_assert(si::ronto<metre>.symbol == "rm"); static_assert(si::ronto<metre>._symbol_ == "rm");
static_assert(si::yocto<metre>.symbol == "ym"); static_assert(si::yocto<metre>._symbol_ == "ym");
static_assert(si::zepto<metre>.symbol == "zm"); static_assert(si::zepto<metre>._symbol_ == "zm");
static_assert(si::atto<metre>.symbol == "am"); static_assert(si::atto<metre>._symbol_ == "am");
static_assert(si::femto<metre>.symbol == "fm"); static_assert(si::femto<metre>._symbol_ == "fm");
static_assert(si::pico<metre>.symbol == "pm"); static_assert(si::pico<metre>._symbol_ == "pm");
static_assert(si::nano<metre>.symbol == "nm"); static_assert(si::nano<metre>._symbol_ == "nm");
static_assert(si::micro<metre>.symbol == symbol_text{u8"µm", "um"}); static_assert(si::micro<metre>._symbol_ == symbol_text{u8"µm", "um"});
static_assert(si::milli<metre>.symbol == "mm"); static_assert(si::milli<metre>._symbol_ == "mm");
static_assert(si::centi<metre>.symbol == "cm"); static_assert(si::centi<metre>._symbol_ == "cm");
static_assert(si::deci<metre>.symbol == "dm"); static_assert(si::deci<metre>._symbol_ == "dm");
static_assert(si::deca<metre>.symbol == "dam"); static_assert(si::deca<metre>._symbol_ == "dam");
static_assert(si::hecto<metre>.symbol == "hm"); static_assert(si::hecto<metre>._symbol_ == "hm");
static_assert(si::kilo<metre>.symbol == "km"); static_assert(si::kilo<metre>._symbol_ == "km");
static_assert(si::mega<metre>.symbol == "Mm"); static_assert(si::mega<metre>._symbol_ == "Mm");
static_assert(si::giga<metre>.symbol == "Gm"); static_assert(si::giga<metre>._symbol_ == "Gm");
static_assert(si::tera<metre>.symbol == "Tm"); static_assert(si::tera<metre>._symbol_ == "Tm");
static_assert(si::peta<metre>.symbol == "Pm"); static_assert(si::peta<metre>._symbol_ == "Pm");
static_assert(si::exa<metre>.symbol == "Em"); static_assert(si::exa<metre>._symbol_ == "Em");
static_assert(si::zetta<metre>.symbol == "Zm"); static_assert(si::zetta<metre>._symbol_ == "Zm");
static_assert(si::yotta<metre>.symbol == "Ym"); static_assert(si::yotta<metre>._symbol_ == "Ym");
static_assert(si::ronna<metre>.symbol == "Rm"); static_assert(si::ronna<metre>._symbol_ == "Rm");
static_assert(si::quetta<metre>.symbol == "Qm"); static_assert(si::quetta<metre>._symbol_ == "Qm");
// scaled_unit // scaled_unit
constexpr auto m_1 = mag<1> * metre; constexpr auto m_1 = mag<1> * metre;