For the purposes of this document,
+
[defs] 3 Terms and definitions [defs] For the purposes of this document,
the terms and definitions given in
IEC 60050-102:2007/AMD3:2021,
IEC 60050-112:2010/AMD2:2020,
ISO 80000-2:2019,
and
N4971,
-and the following apply
. ISO and IEC maintain terminology databases
+and the following apply
. ISO and IEC maintain terminology databases
for use in standardization
at the following addresses:
diff --git a/HEAD/api_reference/gen/derived.qty.html b/HEAD/api_reference/gen/derived.qty.html
new file mode 100644
index 00000000..30697d65
--- /dev/null
+++ b/HEAD/api_reference/gen/derived.qty.html
@@ -0,0 +1,38 @@
+
[derived.qty] 5 Quantities and units library [quantities] namespace mp_units {
+
+template < NamedQuantitySpec Q>
+using to-dimension = decltype ( auto ( Q:: dimension) ) ;
+
+template < typename . . . Expr>
+struct derived-quantity-spec-impl :
+ quantity-spec-interface ,
+ expr-fractions < struct dimensionless, Expr. . . > {
+ using base-type = derived-quantity-spec-impl ;
+ using base = expr-fractions < struct dimensionless, Expr. . . > ;
+
+ static constexpr Dimension auto dimension =
+ expr-map < to-dimension , derived_dimension, struct dimension_one> ( base { } ) ;
+ static constexpr quantity_character character = see below ;
+} ;
+
+template < SymbolicConstant . . . Expr>
+struct derived_quantity_spec final : derived-quantity-spec-impl < Expr. . . > { } ;
+
+}
+derived_ quantity_ spec is used by the library
+to represent the result of a quantity calculus not equal to a named quantity
. [
Example 1 :
constexpr auto area = pow< 2 > ( isq:: length) ;
+int x = area;
+ —
end example ]
+A program that instantiates a specialization of
derived_ quantity_ spec
+that is not a possible result of the library specifications
+is ill-formed, no diagnostic required
. Let
+
Nums and Dens
+be packs denoting the template arguments of
+base :: nums and base :: dens , respectively,QUANTITY-CHARACTER-OF ( Pack) be
+std:: max( { quantity_character:: scalar, expr-type < Pack> :: character. . . } )
+
+andnum_ char be QUANTITY-CHARACTER-OF ( Nums) and
+den_ char be QUANTITY-CHARACTER-OF ( Dens) .
+The member
character is equal to
+
quantity_ character:: scalar if
num_ char = = den_ char is
true , and
+
std:: max( num_ char, den_ char) otherwise
.
\ No newline at end of file
diff --git a/HEAD/api_reference/gen/dimless.qty.html b/HEAD/api_reference/gen/dimless.qty.html
new file mode 100644
index 00000000..bc143772
--- /dev/null
+++ b/HEAD/api_reference/gen/dimless.qty.html
@@ -0,0 +1,6 @@
+
[dimless.qty] 5 Quantities and units library [quantities] namespace mp_units {
+
+struct dimensionless final : quantity_spec< derived_quantity_spec< > > { } ;
+
+}
+
\ No newline at end of file
diff --git a/HEAD/api_reference/gen/full.html b/HEAD/api_reference/gen/full.html
index 8fc785db..2c11e6a9 100644
--- a/HEAD/api_reference/gen/full.html
+++ b/HEAD/api_reference/gen/full.html
@@ -1,4 +1,4 @@
-
14882 The following documents are referred to in the text
+
14882 The following documents are referred to in the text
in such a way that some or all of their content
constitutes requirements of this document
. For dated references, only the edition cited applies
. For undated references,
the latest edition of the referenced document
@@ -6,169 +6,3494 @@ the latest edition of the referenced document
Amendment 3 — International Electrotechnical Vocabulary (IEV) —
Part 102: Mathematics — General concepts and linear algebra
IEC 60050-112:2010/AMD2:2020,
Amendment 2 — International Electrotechnical Vocabulary (IEV) —
-Part 112: Quantities and units
ISO 80000 (all parts), Quantities and units
The C++ Standards Committee
. N4971:
Working Draft, Standard for Programming Language C++ . The C++ Standards Committee
. SD-8:
Standard Library Compatibility . 3 Terms and definitions [defs] For the purposes of this document,
+Part 112: Quantities and units
ISO 80000 (all parts), Quantities and units
The C++ Standards Committee
. N4971:
Working Draft, Standard for Programming Language C++ . The C++ Standards Committee
. P3094R5:
std:: basic_ fixed_ string . The C++ Standards Committee
. SD-8:
Standard Library Compatibility . 3 Terms and definitions [defs] For the purposes of this document,
the terms and definitions given in
IEC 60050-102:2007/AMD3:2021,
IEC 60050-112:2010/AMD2:2020,
ISO 80000-2:2019,
and
N4971,
-and the following apply
. ISO and IEC maintain terminology databases
+and the following apply
. ISO and IEC maintain terminology databases
for use in standardization
at the following addresses:
-
4 Specification [spec] The specification of the mp-units library subsumes
+
4 Specification [spec] [
Note 1 :
This means that, non exhaustively,
:: mp_ units2 is a reserved namespace, andstd:: vector< mp_ units:: type >
is a program-defined specialization and a library-defined specialization
-from the point of view of the C++ standard library and the mp-units library, respectively. —
end note ]
The mp-units library is not part of the C++ implementation
. Detailed specifications for each of the components in the library are in
-
[qties] –
[qties] ,
-as shown in Table
1 . The quantities library (
[qties] )
-describes components for dealing with quantities
. The mp-units library provides the
+from the point of view of the C++ standard library and the mp-units library, respectively
. —
end note ]
The mp-units library is not part of the C++ implementation
. The quantities library (
[quantities] )
+describes components for dealing with quantities
. The mp-units library reserves macro names that start with
-
MP_ UNITSdigit-sequence o p t _ . 5 Quantities library [qties] This Clause describes components for dealing with quantities,
-as summarized in Table
3 . export module mp_units;
+shown in Table 2 . The mp-units library reserves macro names that start with
+
MP_ UNITSdigit-sequence o p t _ . 5 Quantities and units library [quantities] This Clause describes components for dealing with quantities and units,
+as summarized in Table
3 . export module mp_units;
export import mp_units. core;
export import mp_units. systems;
-export module mp_units. core;
+
+export module mp_units. core;
import std;
export namespace mp_units {
-export enum class quantity_character { scalar, vector, tensor } ;
+
-
+
-template < typename Rep>
-constexpr bool treat_as_floating_point = std:: is_floating_point_v< Rep> ;
+enum class character_set : std:: int8_t { utf8, portable, default_character_set = utf8 } ;
-template < typename Rep>
-constexpr bool is_scalar =
- std:: is_floating_point_v< Rep> | | ( std:: is_integral_v< Rep> & & ! is_same_v< Rep, bool > ) ;
+template < std:: size_t N, std:: size_t M>
+class symbol_text;
-template < typename Rep>
-constexpr bool is_vector = false ;
+
-template < typename Rep>
-constexpr bool is_tensor = false ;
+
-template < typename Rep>
-struct quantity_values;
+template < typename T, typename . . . Ts>
+struct per;
+
+template < typename F, int Num, int . . . Den>
+ requires see below
+struct power;
+
+
+
+
+
+
template < typename T>
-struct quantity_like_traits;
+concept Dimension = see below ;
+
+template < typename T, auto D>
+concept DimensionOf = see below ;
+
+
+
+template < symbol_text Symbol>
+struct base_dimension;
+
+template < SymbolicConstant . . . Expr>
+struct derived_dimension;
+
+struct dimension_one;
+inline constexpr dimension_one dimension_one { } ;
+
+
+
+consteval Dimension auto inverse( Dimension auto d) ;
+
+template < std:: intmax_t Num, std:: intmax_t Den = 1 , Dimension D>
+ requires ( Den ! = 0 )
+consteval Dimension auto pow( D d) ;
+consteval Dimension auto sqrt( Dimension auto d) ;
+consteval Dimension auto cbrt( Dimension auto d) ;
+
+
+
+struct dimension_symbol_formatting {
+ character_set char_set = character_set:: default_character_set;
+} ;
+
+template < typename CharT = char , std:: output_iterator< CharT> Out, Dimension D>
+constexpr Out dimension_symbol_to( Out out, D d, const dimension_symbol_formatting& fmt = { } ) ;
+
+template < dimension_symbol_formatting fmt = { } , typename CharT = char , Dimension D>
+consteval std:: string_view dimension_symbol( D) ;
+
+
+
+
template < typename T>
-struct quantity_point_like_traits;
+concept QuantitySpec = see below ;
-
+template < typename T, auto QS>
+concept QuantitySpecOf = see below ;
-template < typename T>
-concept some_ reference = template_of( ^ std:: remove_cvref_t< T> ) = = ^ reference;
+
-template < typename T>
-concept representation = see below ;
+
-template < typename T, quantity_character Ch>
-concept representation_of = see below ;
-
-template < typename T>
-concept some_quantity_spec = see below ;
-
-
+struct is_kind;
+inline constexpr is_kind is_kind { } ;
template < auto . . . >
-struct quantity_spec;
+struct quantity_spec;
-template < auto Q>
-struct kind_of_;
+template < BaseDimension auto Dim, QSProperty auto . . . Args>
+struct quantity_spec< Dim, Args. . . > ;
-template < unspecified . . . Expr>
+template < DerivedQuantitySpec auto Eq, QSProperty auto . . . Args>
+struct quantity_spec< Eq, Args. . . > ;
+
+template < NamedQuantitySpec auto QS, QSProperty auto . . . Args>
+struct quantity_spec< QS, Args. . . > ;
+
+template < NamedQuantitySpec auto QS, DerivedQuantitySpec auto Eq, QSProperty auto . . . Args>
+struct quantity_spec< QS, Eq, Args. . . > ;
+
+
+
+template < SymbolicConstant . . . Expr>
struct derived_quantity_spec;
-
-export template < some_ reference auto R,
- representation_ of < get_quantity_spec( R) . character> Rep = double >
-class quantity;
+
-
-template < unspecified >
-class quantity_point;
+struct dimensionless;
+inline constexpr dimensionless dimensionless { } ;
+
+
+
+template < QuantitySpec Q>
+ requires see below
+struct kind_of_;
+template < QuantitySpec auto Q>
+ requires requires { typename kind_of_< decltype ( Q) > ; }
+inline constexpr kind_of_< decltype ( Q) > kind_of { } ;
+
+
+
+consteval QuantitySpec auto inverse( QuantitySpec auto q) ;
+
+template < std:: intmax_t Num, std:: intmax_t Den = 1 , QuantitySpec Q>
+ requires ( Den ! = 0 )
+consteval QuantitySpec auto pow( Q q) ;
+consteval QuantitySpec auto sqrt( QuantitySpec auto q) ;
+consteval QuantitySpec auto cbrt( QuantitySpec auto q) ;
+
+
+
+
+
+consteval bool implicitly_convertible( QuantitySpec auto from, QuantitySpec auto to) ;
+consteval bool explicitly_convertible( QuantitySpec auto from, QuantitySpec auto to) ;
+consteval bool castable( QuantitySpec auto from, QuantitySpec auto to) ;
+consteval bool interconvertible( QuantitySpec auto qs1, QuantitySpec auto qs2) ;
+
+
+
+template < QuantitySpec Q>
+consteval see below get_kind( Q) ;
+
+
+
+consteval QuantitySpec auto get_common_quantity_spec( QuantitySpec auto . . . qs)
+ requires see below ;
+
+
+
+
+
+
+
+template < typename T>
+concept MagConstant = see below ;
+
+template < typename T>
+concept UnitMagnitude = see below ;
+
+
+
+template < symbol_text Symbol, long double Value>
+ requires ( Value > 0 )
+struct mag_constant;
+
+
+
+template < MagArg auto V>
+constexpr UnitMagnitude auto mag = see below ;
+
+template < std:: intmax_t N, std:: intmax_t D>
+ requires ( N > 0 )
+constexpr UnitMagnitude auto mag_ratio = see below ;
+
+template < MagArg auto Base, int Num, int Den = 1 >
+constexpr UnitMagnitude auto mag_power = see below ;
+
+
+
+inline constexpr struct pi final :
+ mag_constant< { u8"\u03C0" , "pi" } ,
+ std:: numbers:: pi_v< long double > > {
+} pi ;
+
+inline constexpr auto \u03C0 = pi;
+
+
+
+template < Unit auto U>
+constexpr bool space_before_unit_symbol = true ;
+
+template < >
+inline constexpr bool space_before_unit_symbol< one> = false ;
+
+
+
+template < typename T>
+concept Unit = see below ;
+
+template < typename T>
+concept PrefixableUnit = see below ;
+
+template < typename T>
+concept AssociatedUnit = see below ;
+
+template < typename U, auto QS>
+concept UnitOf = see below ;
+
+
+
+
+
+template < UnitMagnitude auto M, Unit U>
+ requires see below
+struct scaled_unit;
+
+
+
+template < symbol_text Symbol, auto . . . >
+struct named_unit;
+
+template < symbol_text Symbol, QuantityKindSpec auto QS>
+ requires see below
+struct named_unit< Symbol, QS> ;
+
+template < symbol_text Symbol, QuantityKindSpec auto QS, PointOrigin auto PO>
+ requires see below
+struct named_unit< Symbol, QS, PO> ;
+
+template < symbol_text Symbol>
+ requires see below
+struct named_unit< Symbol> ;
+
+template < symbol_text Symbol, Unit auto U>
+ requires see below
+struct named_unit< Symbol, U> ;
+
+template < symbol_text Symbol, Unit auto U, PointOrigin auto PO>
+ requires see below
+struct named_unit< Symbol, U, PO> ;
+
+template < symbol_text Symbol, AssociatedUnit auto U, QuantityKindSpec auto QS>
+ requires see below
+struct named_unit< Symbol, U, QS> ;
+
+template < symbol_text Symbol, AssociatedUnit auto U, QuantityKindSpec auto QS,
+ PointOrigin auto PO>
+ requires see below
+struct named_unit< Symbol, U, QS, PO> ;
+
+
+
+template < symbol_text Symbol, UnitMagnitude auto M, PrefixableUnit auto U>
+ requires see below
+struct prefixed_unit;
+
+
+
+template < Unit U1, Unit U2, Unit . . . Rest>
+struct common_unit;
+
+
+
+template < SymbolicConstant . . . Expr>
+struct derived_unit;
+
+
+
+struct one;
+inline constexpr one one { } ;
+
+
+
+inline constexpr struct percent final : named_unit< "%" , mag_ratio< 1 , 100 > * one> {
+} percent ;
+
+inline constexpr struct per_mille final :
+ named_unit< symbol_text{ u8"\u2030" , "%o" } ,
+ mag_ratio< 1 , 1000 > * one> {
+} per_mille ;
+
+inline constexpr struct parts_per_million final :
+ named_unit< "ppm" , mag_ratio< 1 , 1'000'000 > * one> {
+} parts_per_million ;
+
+inline constexpr auto ppm = parts_per_million;
+
+
+
+consteval Unit auto inverse( Unit auto u) ;
+
+template < std:: intmax_t Num, std:: intmax_t Den = 1 , Unit U>
+ requires see below
+consteval Unit auto pow( U u) ;
+consteval Unit auto sqrt( Unit auto u) ;
+consteval Unit auto cbrt( Unit auto u) ;
+consteval Unit auto square( Unit auto u) ;
+consteval Unit auto cubic( Unit auto u) ;
+
+
+
+template < Unit From, Unit To>
+consteval bool convertible( From from, To to) ;
+
+
+
+consteval QuantitySpec auto get_quantity_spec( AssociatedUnit auto u) ;
+consteval Unit auto get_unit( AssociatedUnit auto u) ;
+
+consteval Unit auto get_common_unit( Unit auto . . . us)
+ requires see below ;
+
+
+
+enum class unit_symbol_solidus : std:: int8_t {
+ one_denominator,
+ always,
+ never,
+ default_denominator = one_denominator
+} ;
+
+enum class unit_symbol_separator : std:: int8_t {
+ space,
+ half_high_dot,
+ default_separator = space
+} ;
+
+struct unit_symbol_formatting {
+ character_set char_set = character_set:: default_character_set;
+ unit_symbol_solidus solidus = unit_symbol_solidus:: default_denominator;
+ unit_symbol_separator separator = unit_symbol_separator:: default_separator;
+} ;
+
+template < typename CharT = char , std:: output_iterator< CharT> Out, Unit U>
+constexpr Out unit_symbol_to( Out out, U u, const unit_symbol_formatting& fmt = { } ) ;
+
+template < unit_symbol_formatting fmt = { } , typename CharT = char , Unit U>
+consteval std:: string_view unit_symbol( U) ;
+
+
+
+template < typename T>
+concept Reference = see below ;
+
+template < typename T, auto QS>
+concept ReferenceOf = see below ;
+
+
+
+template < QuantitySpec Q, Unit U>
+struct reference;
+
+
+
+template < typename FwdRep, Reference R,
+ RepresentationOf < get_quantity_spec( R{ } ) > Rep = std:: remove_cvref_t< FwdRep> >
+ requires ( ! OffsetUnit < decltype ( get_unit( R{ } ) ) > )
+constexpr quantity< R{ } , Rep> operator * ( FwdRep& & lhs, R r) ;
+
+template < typename FwdRep, Reference R,
+ RepresentationOf < get_quantity_spec( R{ } ) > Rep = std:: remove_cvref_t< FwdRep> >
+ requires ( ! OffsetUnit < decltype ( get_unit( R{ } ) ) > )
+constexpr Quantity auto operator / ( FwdRep& & lhs, R) ;
+
+template < typename FwdQ, Reference R, Quantity Q = std:: remove_cvref_t< FwdQ> >
+constexpr Quantity auto operator * ( FwdQ& & q, R) ;
+
+template < typename FwdQ, Reference R, Quantity Q = std:: remove_cvref_t< FwdQ> >
+constexpr Quantity auto operator / ( FwdQ& & q, R) ;
+
+template < Reference R, typename Rep>
+ requires RepresentationOf < std:: remove_cvref_t< Rep> , get_quantity_spec( R{ } ) >
+constexpr auto operator * ( R, Rep& & ) = delete ;
+
+template < Reference R, typename Rep>
+ requires RepresentationOf < std:: remove_cvref_t< Rep> , get_quantity_spec( R{ } ) >
+constexpr auto operator / ( R, Rep& & ) = delete ;
+
+template < Reference R, typename Q>
+ requires Quantity < std:: remove_cvref_t< Q> >
+constexpr auto operator * ( R, Q& & ) = delete ;
+
+template < Reference R, typename Q>
+ requires Quantity < std:: remove_cvref_t< Q> >
+constexpr auto operator / ( R, Q& & ) = delete ;
+
+
+
+template < typename Q, typename U>
+consteval QuantitySpec auto get_quantity_spec( reference< Q, U> ) ;
+
+template < typename Q, typename U>
+consteval Unit auto get_unit( reference< Q, U> ) ;
+
+consteval AssociatedUnit auto get_common_reference( AssociatedUnit auto u1,
+ AssociatedUnit auto u2,
+ AssociatedUnit auto . . . rest)
+ requires see below ;
+
+template < Reference R1, Reference R2, Reference . . . Rest>
+consteval Reference auto get_common_reference( R1 r1, R2 r2, Rest. . . rest)
+ requires see below ;
+
+
+
+enum class quantity_character { scalar, complex, vector, tensor } ;
+
+
+
+
+
+template < typename Rep>
+constexpr bool treat_as_floating_point = see below ;
+
+
+
+template < typename T>
+constexpr bool disable_scalar = false ;
+template < >
+inline constexpr bool disable_scalar< bool > = true ;
+template < typename T>
+constexpr bool disable_scalar< std:: complex< T> > = true ;
+
+template < typename T>
+constexpr bool disable_complex = false ;
+
+template < typename T>
+constexpr bool disable_vector = false ;
+
+
+
+template < typename Rep>
+struct representation_values;
+
+
+
+inline namespace unspecified {
+
+inline constexpr unspecified real = unspecified ;
+inline constexpr unspecified imag = unspecified ;
+inline constexpr unspecified modulus = unspecified ;
+
+inline constexpr unspecified magnitude = unspecified ;
}
- export module mp_units. systems;
+
+
+
+template < typename T>
+concept Representation = see below ;
+
+template < typename T, quantity_character Ch>
+concept RepresentationOf = see below ;
+
+
+
+
+
+template < typename T>
+struct quantity_like_traits;
+
+template < typename T>
+concept QuantityLike = see below ;
+
+
+
+template < typename T>
+concept Quantity = see below ;
+
+template < typename Q, auto QS>
+concept QuantityOf = see below ;
+
+template < Reference auto R, RepresentationOf < get_quantity_spec( R) > Rep = double >
+class quantity;
+
+
+
+template < Reference R>
+struct delta_;
+
+template < Reference auto R>
+constexpr delta_< decltype ( R) > delta { } ;
+
+
+
+template < Unit auto ToU, see below >
+ requires see below
+constexpr Quantity auto value_cast( see below q) ;
+
+template < Representation ToRep, see below >
+ requires see below
+constexpr quantity< see below , ToRep> value_cast( see below q) ;
+
+template < Unit auto ToU, Representation ToRep, see below >
+ requires see below
+constexpr Quantity auto value_cast( see below q) ;
+template < Representation ToRep, Unit auto ToU, see below >
+ requires see below
+constexpr Quantity auto value_cast( see below q) ;
+
+template < Quantity ToQ, see below >
+ requires see below
+constexpr Quantity auto value_cast( see below q) ;
+
+template < QuantitySpec auto ToQS, see below >
+ requires see below
+constexpr Quantity auto quantity_cast( see below q) ;
+
+}
+
+
+
+template < mp_units:: Quantity Q1, mp_units:: Quantity Q2>
+ requires see below
+struct std:: common_type< Q1, Q2> ;
+
+template < mp_units:: Quantity Q, mp_units:: Representation Value>
+ requires see below
+struct std:: common_type< Q, Value> ;
+
+template < mp_units:: Quantity Q, mp_units:: Representation Value>
+ requires requires { typename std:: common_type< Q, Value> ; }
+struct std:: common_type< Value, Q> : std:: common_type< Q, Value> { } ;
+
+namespace mp_units {
+
+
+
+
+
+
+
+template < typename T>
+concept PointOrigin = see below ;
+
+template < typename T, auto QS>
+concept PointOriginFor = see below ;
+
+
+
+
+
+template < QuantitySpec auto QS>
+struct absolute_point_origin;
+
+
+
+template < QuantityPoint auto QP>
+struct relative_point_origin;
+
+
+
+template < QuantitySpec auto QS>
+struct zeroth_point_origin_;
+
+template < QuantitySpec auto QS>
+constexpr zeroth_point_origin_< QS> zeroth_point_origin { } ;
+
+
+
+template < Reference R>
+consteval PointOriginFor < get_quantity_spec( R{ } ) > auto default_point_origin( R) ;
+
+
+
+template < typename T>
+struct quantity_point_like_traits;
+
+template < typename T>
+concept QuantityPointLike = see below ;
+
+
+
+template < typename T>
+concept QuantityPoint = see below ;
+
+template < typename QP, auto V>
+concept QuantityPointOf = see below ;
+
+template < Reference auto R,
+ PointOriginFor < get_quantity_spec( R) > auto PO = default_point_origin( R) ,
+ RepresentationOf < get_quantity_spec( R) > Rep = double >
+class quantity_point;
+
+
+
+template < Reference R>
+struct point_;
+
+template < Reference auto R>
+constexpr point_< decltype ( R) > point { } ;
+
+
+
+template < Unit auto ToU, see below >
+ requires see below
+constexpr QuantityPoint auto value_cast( see below qp) ;
+
+template < Representation ToRep, see below >
+ requires see below
+constexpr quantity_point< see below , see below , ToRep> value_cast( see below qp) ;
+
+template < Unit auto ToU, Representation ToRep, see below >
+ requires see below
+constexpr QuantityPoint auto value_cast( see below qp) ;
+template < Representation ToRep, Unit auto ToU, see below >
+ requires see below
+constexpr QuantityPoint auto value_cast( see below qp) ;
+
+template < Quantity ToQ, see below >
+ requires see below
+constexpr QuantityPoint auto value_cast( see below qp) ;
+
+template < QuantityPoint ToQP, see below >
+ requires see below
+constexpr QuantityPoint auto value_cast( see below qp) ;
+
+template < QuantitySpec auto ToQS, see below >
+ requires see below
+constexpr QuantityPoint auto quantity_cast( see below qp) ;
+
+}
+export module mp_units. systems;
export import mp_units. core;
import std;
export namespace mp_units {
+
+
+template < typename Rep, typename Period>
+struct quantity_like_traits< std:: chrono:: duration< Rep, Period> > ;
+
+template < typename Clock>
+struct chrono_point_origin_;
+template < typename Clock>
+constexpr chrono_point_origin_< Clock> chrono_point_origin { } ;
+
+template < typename Clock, typename Rep, typename Period>
+struct quantity_point_like_traits<
+ std:: chrono:: time_point< Clock, std:: chrono:: duration< Rep, Period> > > ;
+
}
-consteval bool converts-to-base-subobject-of ( std:: meta type, std:: meta template_name) ;
-
Preconditions :
is_ type( type) & & is_ template( template_ name) is
true . Returns :
true if
-
[ : type: ] has an unambiguous and accessible base
-that is a specialization of
[ : template_ name: ] , and
-
false otherwise
. template < typename Rep>
-constexpr bool is_scalar =
- std:: is_floating_point_v< Rep> | | ( std:: is_integral_v< Rep> & & ! is_same_v< Rep, bool > ) ;
+
template < typename T, template < see below > typename U>
+consteval bool is-specialization-of ( ) ;
+template < typename T, template < see below > typename U>
+consteval bool is-derived-from-specialization-of ( ) ;
+
Returns :
For the first signature,
+
true of
T is a specialization of
U , and
+
false otherwise
. For the second signature,
+
true if
T has exactly one public base class
+that is a specialization of
U
+and has no other base class that is a specialization of
U , and
+
false otherwise
. Remarks : An implementation provides enough overloads for all arguments to
U . namespace mp_units {
-template < typename Rep>
-constexpr bool is_vector = false ;
+struct ratio {
+ std:: intmax_t num;
+ std:: intmax_t den;
-template < typename Rep>
-constexpr bool is_tensor = false ;
-export template < typename T>
-concept representation =
- ( is_scalar< T> | | is_vector< T> | | is_tensor< T> ) & & std:: regular< T> & & scalable < T> ;
-
export template < typename T, quantity_character Ch>
-concept representation_ of =
- representation < T> & & ( ( Ch = = quantity_character:: scalar & & is_scalar< T> ) | |
- ( Ch = = quantity_character:: vector & & is_vector< T> ) | |
- ( Ch = = quantity_character:: tensor & & is_tensor< T> ) ) ;
-
template < typename T>
-concept named-quantity-spec =
- ( converts-to-base-subobject-of ( ^ T, ^ quantity_spec) & & template_of( ^ T) ! = ^ kind_of_) ;
+ consteval ratio ( std:: intmax_t n, std:: intmax_t d = 1 ) ;
+
+ friend consteval bool operator = = ( ratio , ratio ) = default ;
+ friend consteval auto operator < = > ( ratio lhs, ratio rhs) { return ( lhs - rhs) . num < = > 0 ; }
+
+ friend consteval ratio operator - ( ratio r) { return { - r. num, r. den} ; }
+
+ friend consteval ratio operator + ( ratio lhs, ratio rhs)
+ {
+ return { lhs. num * rhs. den + lhs. den * rhs. num, lhs. den * rhs. den} ;
+ }
+
+ friend consteval ratio operator - ( ratio lhs, ratio rhs) { return lhs + ( - rhs) ; }
+
+ friend consteval ratio operator * ( ratio lhs, ratio rhs) ;
+
+ friend consteval ratio operator / ( ratio lhs, ratio rhs)
+ {
+ return lhs * ratio { rhs. den, rhs. num} ;
+ }
+} ;
+
+consteval bool is-integral ( ratio r) { return r. num % r. den = = 0 ; }
+
+consteval ratio common-ratio ( ratio r1, ratio r2) ;
+
+}
+
ratio represents the rational number
num / den . Unless otherwise specified,
+in the following descriptions,
+let
R( r) be
std:: ratio< N, D> ,
+where
N and
D are the values of
r. num and
r. den . consteval ratio ( std:: intmax_t n, std:: intmax_t d = 1 ) ;
+
Let
N and
D be the values of
n and
d . Let
R be
std:: ratio< N, D> . Effects : Equivalent to
+
R . Postconditions :
num = = R:: num & & den = = R:: den is
true . friend consteval ratio operator * ( ratio lhs, ratio rhs) ;
+
Let
Res be
std:: ratio_ multiply< R( lhs) , R( rhs) > . Effects : Equivalent to:
+return { Res:: num, Res:: den} ;
consteval ratio common-ratio ( ratio r1, ratio r2) ;
+
Let Res be equal to
+std:: common_type< std:: chrono:: duration< int , R( r1) > ,
+ std:: chrono:: duration< int , R( r2) > > :: type:: period
+
Effects : Equivalent to:
+return { Res:: num, Res:: den} ;
namespace mp_units {
+
+template < std:: size_t N, std:: size_t M>
+class symbol_text {
+public :
+ std:: fixed_u8string< N> utf8 ;
+ std:: fixed_string< M> portable ;
+
+
+ constexpr symbol_text( char portable) ;
+ consteval symbol_text( const char ( & portable) [ N + 1 ] ) ;
+ constexpr symbol_text( const std:: fixed_string< N> & portable) ;
+ consteval symbol_text( const char8_t ( & utf8) [ N + 1 ] , const char ( & portable) [ M + 1 ] ) ;
+ constexpr symbol_text( const std:: fixed_u8string< N> & utf8,
+ const std:: fixed_string< M> & portable) ;
+
+
+ constexpr const auto & utf8 ( ) const { return utf8 ; }
+ constexpr const auto & portable ( ) const { return portable ; }
+ constexpr bool empty ( ) const { return utf8( ) . empty( ) ; }
+
+
+ template < std:: size_t N2, std:: size_t M2>
+ friend constexpr symbol_text< N + N2, M + M2> operator + ( const symbol_text& lhs,
+ const symbol_text< N2, M2> & rhs) ;
+
+
+ template < std:: size_t N2, std:: size_t M2>
+ friend constexpr bool operator = = ( const symbol_text& lhs,
+ const symbol_text< N2, M2> & rhs) noexcept ;
+ template < std:: size_t N2, std:: size_t M2>
+ friend constexpr auto operator < = > ( const symbol_text& lhs,
+ const symbol_text< N2, M2> & rhs) noexcept ;
+} ;
+
+symbol_text( char ) - > symbol_text< 1 , 1 > ;
+
+template < std:: size_t N>
+symbol_text( const char ( & ) [ N] ) - > symbol_text< N - 1 , N - 1 > ;
+
+template < std:: size_t N>
+symbol_text( const std:: fixed_string< N> & ) - > symbol_text< N, N> ;
+
+template < std:: size_t N, std:: size_t M>
+symbol_text( const char8_t ( & ) [ N] , const char ( & ) [ M] ) - > symbol_text< N - 1 , M - 1 > ;
+
+template < std:: size_t N, std:: size_t M>
+symbol_text( const std:: fixed_u8string< N> & , const std:: fixed_string< M> & ) - > symbol_text< N, M> ;
+
+}
+symbol_ text represents a symbol text
. utf8 stores its UTF-8 representation, and
+
portable stores its portable representation
. In the descriptions that follow,
+it is a
Precondition that
+
values of char are in the basic literal character set (N4971, [lex.charset] ), and for a parameter of the form const CharT ( & txt ) [ M ] ,
+( txt [ M - 1 ] = = CharT ( ) ) is true . constexpr symbol_text( char portable) ;
+consteval symbol_text( const char ( & portable) [ N + 1 ] ) ;
+constexpr symbol_text( const std:: fixed_string< N> & portable) ;
+consteval symbol_text( const char8_t ( & utf8) [ N + 1 ] , const char ( & portable) [ M + 1 ] ) ;
+constexpr symbol_text( const std:: fixed_u8string< N> & utf8, const std:: fixed_string< M> & portable) ;
+
For the constructors without a parameter named utf8 ,
+let utf8 be:
+std:: bit_cast< std:: fixed_u8string< N> > ( std:: basic_fixed_string( portable) )
+
Effects : Equivalent to the mem-initializer-list :
+utf8 { utf8} , portable { portable}
+
template < std:: size_t N2, std:: size_t M2>
+friend constexpr symbol_text< N + N2, M + M2> operator + ( const symbol_text& lhs,
+ const symbol_text< N2, M2> & rhs) ;
+
Effects : Equivalent to:
+return symbol_text< N + N2, M + M2> ( lhs. utf8( ) + rhs. utf8( ) ,
+ lhs. portable( ) + rhs. portable( ) ) ;
+
template < std:: size_t N2, std:: size_t M2>
+friend constexpr bool operator = = ( const symbol_text& lhs,
+ const symbol_text< N2, M2> & rhs) noexcept ;
+template < std:: size_t N2, std:: size_t M2>
+friend constexpr auto operator < = > ( const symbol_text& lhs,
+ const symbol_text< N2, M2> & rhs) noexcept ;
+
Effects : Equivalent to:
+return std:: make_tuple( std:: cref( lhs. utf8( ) ) , std:: cref( lhs. portable( ) ) ) @
+ std:: make_tuple( std:: cref( rhs. utf8( ) ) , std:: cref( rhs. portable( ) ) ) ;
+
Subclause
[qty. sym. expr] specifies the components
+used to maintain ordered, simplified, and readable
+argument lists in the names of specializations
. [
Example 1 :
using namespace si:: unit_symbols;
+int x = kg * km / square( h) ;
+
+
+The library ensures
decltype ( kg * km / square( h) ) is styled-like as commented in diagnostics,
+provided that, in the implementation-defined total order of types,
+
decltype ( kg) is less than
decltype ( km) . —
end example ]
template < typename T>
+concept SymbolicConstant =
+ std:: is_empty_v< T> & & std:: is_final_v< T> & & std:: is_trivially_default_constructible_v< T> & &
+ std:: is_trivially_copy_constructible_v< T> & & std:: is_trivially_move_constructible_v< T> & &
+ std:: is_trivially_destructible_v< T> ;
+
The concept
SymbolicConstant
+is used to constrain the types
+that are used in symbolic expressions
. namespace mp_units {
+
+template < typename T, typename . . . Ts>
+struct per final { } ;
+
+}
+per is used to store arguments with negative exponents
. A specialization of
per
+represents the product of the inverse of its template arguments
. A program that instantiates a specialization of
per
+that is not a possible result of the library specifications
+is ill-formed, no diagnostic required
. namespace mp_units {
+
+template < typename F, int Num, int . . . Den>
+ requires see below
+struct power final {
+ using factor = F;
+ static constexpr ratio exponent { Num, Den. . . } ;
+} ;
+
+}
+ [
Note 1 :
Den is optional to shorten the type name when
Den is
1 . —
end note ]
+A program that instantiates a specialization of
power
+that is not a possible result of the library specifications
+is ill-formed, no diagnostic required
. Let
r be
ratio { Num, Den. . . } . Let
is-valid-ratio be
+
true if
r is a valid constant expression, and
+
false otherwise
. The expression in the requires-clause is equivalent to:
+is-valid-ratio & & ( r > ratio { 0 } ) & & ( r ! = ratio { 1 } )
+
template < typename T>
+using expr-type = see below ;
+expr-type < T> denotes
+
U if
T is of the form
power< U, Ints. . . > , and
+
T otherwise
. template < typename T, typename U>
+consteval bool type-less-impl ( ) ;
+
Returns :
true if
T is less than
U
+in an implementation-defined total order for types, and
+
false otherwise
. template < typename Lhs, typename Rhs>
+struct type-less :
+ std:: bool_constant< is-specialization-of < Rhs, power> ( ) | |
+ type-less-impl < expr-type < Lhs> , expr-type < Rhs> > ( ) > { } ;
+type-less meets the requirements of
+the
Pred parameter of the symbolic expression algorithms below
. template < typename . . . Ts>
+struct type-list { } ;
+
+template < typename OneType, typename . . . Ts>
+struct expr-fractions {
+ using num = see below ;
+ using den = see below ;
+}
+expr-fractions divides a symbolic expression to numerator and denominator parts
. Let
EF be a specialization of
expr-fractions . If
EF is of the form
expr-fractions < OneType, Ts. . . , per< Us. . . > > ,
+then
+
EF:: num denotes type-list < Ts. . . > , andEF:: den denotes type-list < Us. . . > . Otherwise,
EF is of the form
expr-fractions < OneType, Ts. . . > , and
+
EF:: num denotes type-list < Ts. . . > , andEF:: den denotes type-list < > . The symbolic expression algorithms perform operations on symbolic constants
. [
Example 1 :
The dimension
dim_ length , the quantity
time , and the unit
one are symbolic constants
. —
end example ]
+The algorithms also support
+powers with a symbolic constant base and a rational exponent,
+products thereof, and
+fractions thereof
. template < template < typename . . . > typename To, typename OneType,
+ template < typename , typename > typename Pred = type-less , typename Lhs, typename Rhs>
+consteval auto expr-multiply ( Lhs, Rhs) ;
+
+template < template < typename . . . > typename To, typename OneType,
+ template < typename , typename > typename Pred = type-less , typename Lhs, typename Rhs>
+consteval auto expr-divide ( Lhs lhs, Rhs rhs) ;
+
+template < template < typename . . . > typename To, typename OneType, typename T>
+consteval auto expr-invert ( T) ;
+
+template < std:: intmax_t Num, std:: intmax_t Den, template < typename . . . > typename To,
+ typename OneType, template < typename , typename > typename Pred = type-less , typename T>
+ requires ( Den ! = 0 )
+consteval auto expr-pow ( T) ;
+
Mandates :
OneType is the neutral element (IEC 60050, 102-01-19 ) of the operation, andPred is a Cpp17BinaryTypeTrait (N4971, [meta.rqmts] )
+with a base characteristic of std:: bool_ constant< B> . Pred< T, U> implements a total order for types;
+
B is
true if
T is ordered before
U , and
false otherwise
. First, inputs to the operations are obtained from the types of the function parameters
. If the type of a function parameter is:
+
A specialization of
To ,
+then its input is the product of its template arguments, and
+the following also apply
. A specialization of
per ,
+then its input is the product of the inverse of its template arguments, and
+the following also apply
. A specialization of the form
power< F, Num> ,
+then its input is
F Num , or
+a specialization of the form
power< F, Num, Den> ,
+then its input is
F Num / Den , and
+the following also applies
. Otherwise, the input is the symbolic constant itself
. [
Example 2 :
Item by item, this algorithm step goes from the C++ parameter type
+
decltype ( km / square( h) ) ,
+styled in diagnostics like
+
derived_ unit< si:: kilo_< si:: metre> , per< power< non_ si:: hour, 2 > > ,
+
to decltype ( km) ×per< power< decltype ( h) , 2 > (product of To 's arguments), to decltype ( km) × 1 / power< decltype ( h) , 2 > (product of inverse of per 's arguments), to decltype ( km) × 1 / decltype ( h) 2 (power s as powers), to a × 1 / b 2 where a = decltype ( km) and b = decltype ( h) (symbolic substitution)
+in the mathematical domain. —
end example ]
Then, the operation takes place:
+
expr-multiply multiplies its inputs,expr-divide divides the input of its first parameter by the input of its second parameter,expr-invert divides 1 by its input, andexpr-pow raises its input to the Num / Den . Finally, let
r be the result of the operation simplified as follows:
+
All terms are part of the same fraction (if any)
. There is at most a single term with a given symbolic constant
. There are no negative exponents
. 1 is only present as
r and as a numerator with a denominator not equal to
1 . [
Example 3 :
Item by item:
x × 1 / y × 1 / x 2 = x / ( y x 2 ) (single fraction)
= x − 1 / y (unique symbolic constants)
= 1 / ( x 1 y ) (positive exponents)
= 1 / ( x y ) (non-redundant 1 s)
—
end example ]
Returns :
r is mapped to the return type:
+
If
r = 1 , returns
OneType{ } . Otherwise, if
r is a symbolic constant, returns
r . Otherwise, first applies the following mappings to the terms of
r :
+
x n / d is mapped to power< x , n , d > , and
+x n is mapped to power< x , n > , and1 is mapped to OneType{ } . Then, a denominator
x of
r (if any) is mapped to
per< x > . Then, sorts
r without
per (if any) and
+the template arguments of
per (if any)
+according to
Pred . Finally, returns
To< r > { } , where
per (if any) is the last argument
. Remarks : A valid template argument list for
To and
per
+is formed by interspersing commas between each mapped term
. If a mapping to
std:: intmax_ t is not representable,
+the program is ill-formed
. expr-map maps the contents of one symbolic expression to another resulting in a different type list
. template < template < typename > typename Proj, template < typename . . . > typename To, typename OneType,
+ template < typename , typename > typename Pred = type-less , typename T>
+consteval auto expr-map ( T) ;
+
Let
+
expr-type-map < U> be
+power< Proj< F> , Ints. . . > if U is of the form power< F, Ints. . . > , and
+Proj< U> otherwise,map-power ( u) be
+pow< Ints. . . > ( F{ } ) if decltype ( u) is of the form power< F, Ints. . . > , and
+u otherwise, andNums and Dens
+be packs denoting the template arguments of
+T:: nums and T:: dens , respectively. Returns : ( OneType{ } * . . . * map-power ( expr-type-map < Nums> { } ) ) /
+( OneType{ } * . . . * map-power ( expr-type-map < Dens> { } ) )
+
template < typename T>
+concept Dimension = SymbolicConstant < T> & & std:: derived_from< T, dimension-interface > ;
template < typename T>
-concept some_ quantity_ spec =
- named-quantity-spec < T> | |
- detail:: IntermediateDerivedQuantitySpec< T> | |
- template_of( ^ T) = = ^ kind_of;
-
A
quantity type
-is a type
Q
-that is a specialization of
quantity or
quantity_ point . Q represents a quantity (
IEC 60050, 112-01-01 )
-with
Q :: rep as its number
-and
Q :: reference as its reference
. Each class template defined in subclause
[qty. types]
-has data members and special members specified below, and
-has no base classes or members other than those specified
. namespace mp_units {
+concept BaseDimension =
+ Dimension < T> & & ( is-derived-from-specialization-of < T, base_dimension> ( ) ) ;
-export template < some_ reference auto R,
- representation_ of < get_quantity_spec( R) . character> Rep = double >
-class quantity { unspecified } ;
+template < typename T, auto D>
+concept DimensionOf = Dimension < T> & & Dimension < decltype ( D) > & & ( T{ } = = D) ;
+namespace mp_units {
+
+template < symbol_text Symbol>
+struct base_dimension : dimension-interface {
+ static constexpr auto symbol = Symbol;
+} ;
}
-Let
Q be a specialization of
quantity . namespace mp_units {
+
Symbol is its symbolic representation
. [
Example 1 :
inline constexpr struct dim_length final : base_dimension< "L" > { } dim_length;
+ —
end example ]
namespace mp_units {
-export template < unspecified >
-class quantity_point { unspecified } ;
+template < typename . . . Expr>
+struct derived-dimension-impl
+ : expr-fractions < struct dimension_one, Expr. . . > { } ;
+
+template < SymbolicConstant . . . Expr>
+struct derived_dimension final : dimension-interface , derived-dimension-impl < Expr. . . > { } ;
}
- Let
Q be a quantity point type
. If
Rep is a vector,
-
Q represents a position vector
.
\ No newline at end of file
+
derived_ dimension is used by the library
+to represent the dimension of a derived quantity (
IEC 60050, 112-01-10 )
. [
Example 2 :
constexpr auto dim_acceleration = isq:: speed. dimension / isq:: dim_time;
+int x = dim_acceleration;
+
+ —
end example ]
+A program that instantiates a specialization of
derived_ dimension
+that is not a possible result of the library specifications
+is ill-formed, no diagnostic required
. namespace mp_units {
+
+struct dimension_one final : dimension-interface , derived-dimension-impl < > { } ;
+
+}
+Returns :
expr-multiply < derived_ dimension, struct dimension_ one> ( Lhs{ } , Rhs{ } ) . Returns :
expr-divide < derived_ dimension, struct dimension_ one> ( Lhs{ } , Rhs{ } ) . Returns :
std:: is_ same_ v< Lhs, Rhs> . Returns :
dimension_ one / d . template < std:: intmax_t Num, std:: intmax_t Den = 1 , Dimension D>
+ requires ( Den ! = 0 )
+consteval Dimension auto pow( D d) ;
+
Returns :
expr-pow < Num, Den, derived_ dimension, struct dimension_ one> ( d) . template < typename CharT = char , std:: output_iterator< CharT> Out, Dimension D>
+constexpr Out dimension_symbol_to( Out out, D d, const dimension_symbol_formatting& fmt = { } ) ;
+
template < dimension_symbol_formatting fmt = { } , typename CharT = char , Dimension D>
+consteval std:: string_view dimension_symbol( D) ;
+
Effects : Equivalent to:
+TBD.
+
template < typename T>
+concept QuantitySpec = SymbolicConstant < T> & & std:: derived_from< T, quantity-spec-interface > ;
+
+template < typename T>
+concept QuantityKindSpec =
+ QuantitySpec < T> & & is-specialization-of < T, kind_of_> ( ) ;
+
+template < typename T>
+concept NamedQuantitySpec =
+ QuantitySpec < T> & & is-derived-from-specialization-of < T, quantity_spec> ( ) & &
+ ( ! QuantityKindSpec < T> ) ;
+
+template < typename T>
+concept DerivedQuantitySpec =
+ QuantitySpec < T> & &
+ ( is-specialization-of < T, derived_quantity_spec> ( ) | |
+ ( QuantityKindSpec < T> & &
+ is-specialization-of < decltype ( auto ( T:: quantity-spec ) ) , derived_quantity_spec> ( ) ) ) ;
+
+template < auto Child, auto Parent>
+concept ChildQuantitySpecOf = ( is-child-of ( Child, Parent) ) ;
+
+template < auto To, auto From>
+concept NestedQuantityKindSpecOf =
+ QuantitySpec < decltype ( From) > & & QuantitySpec < decltype ( To) > & &
+ ( get_kind( From) ! = get_kind( To) ) & & ChildQuantitySpecOf < To, get_kind( From) . quantity-spec > ;
+
+template < auto From, auto To>
+concept QuantitySpecConvertibleTo =
+ QuantitySpec < decltype ( From) > & & QuantitySpec < decltype ( To) > & & implicitly_convertible( From, To) ;
+
+template < auto From, auto To>
+concept QuantitySpecExplicitlyConvertibleTo =
+ QuantitySpec < decltype ( From) > & & QuantitySpec < decltype ( To) > & & explicitly_convertible( From, To) ;
+
+template < auto From, auto To>
+concept QuantitySpecCastableTo =
+ QuantitySpec < decltype ( From) > & & QuantitySpec < decltype ( To) > & & castable( From, To) ;
+
+template < typename T, auto QS>
+concept QuantitySpecOf =
+ QuantitySpec < T> & & QuantitySpec < decltype ( QS) > & & QuantitySpecConvertibleTo < T{ } , QS> & &
+ ! NestedQuantityKindSpecOf < T{ } , QS> & &
+ ( QuantityKindSpec < T> | | ! NestedQuantityKindSpecOf < QS, T{ } > ) ;
+
+template < typename T>
+concept QSProperty = ( ! QuantitySpec < T> ) ;
+
namespace mp_units {
+
+struct is_kind { } ;
+
+template < BaseDimension auto Dim, QSProperty auto . . . Args>
+struct quantity_spec< Dim, Args. . . > : quantity-spec-interface {
+ using base-type = quantity_spec;
+ static constexpr BaseDimension auto dimension = Dim;
+ static constexpr quantity_character character = see below ;
+} ;
+
+template < DerivedQuantitySpec auto Eq, QSProperty auto . . . Args>
+struct quantity_spec< Eq, Args. . . > : quantity-spec-interface {
+ using base-type = quantity_spec;
+ static constexpr auto equation = Eq;
+ static constexpr Dimension auto dimension = Eq. dimension;
+ static constexpr quantity_character character = see below ;
+} ;
+
+template < NamedQuantitySpec auto QS, QSProperty auto . . . Args>
+struct quantity_spec< QS, Args. . . > : quantity-spec-interface {
+ using base-type = quantity_spec;
+ static constexpr auto parent = QS;
+ static constexpr auto equation = parent . equation ;
+
+ static constexpr Dimension auto dimension = parent . dimension;
+ static constexpr quantity_character character = see below ;
+} ;
+
+template < NamedQuantitySpec auto QS, DerivedQuantitySpec auto Eq, QSProperty auto . . . Args>
+ requires QuantitySpecExplicitlyConvertibleTo < Eq, QS>
+struct quantity_spec< QS, Eq, Args. . . > : quantity-spec-interface {
+ using base-type = quantity_spec;
+ static constexpr auto parent = QS;
+ static constexpr auto equation = Eq;
+ static constexpr Dimension auto dimension = parent . dimension;
+ static constexpr quantity_character character = see below ;
+} ;
+
+}
+ A specialization of
quantity_ spec is used as a base type when defining a named quantity
. In the following descriptions, let
Q be a named quantity defined with an alluded signature
. Let
Ch be an enumerator value of
quantity_ character . The possible arguments to
quantity_ spec are
+
( a base quantity dimension , Ch o p t ) ,( a quantity calculus , Ch o p t ) ,( a named quantity , Ch o p t , is_kind o p t ) , and( a named quantity , a quantity calculus , Ch o p t , is_kind o p t ) . If the first argument is a base quantity dimension,
+then
Q is that base quantity (
IEC 60050, 112-01-08 )
. If an argument is a quantity calculus (
IEC 60050, 112-01-30 )
C ,
+then
Q is implicitly convertible from
C . The member
character represents
+the set of the numerical value of
Q (
[qty. char. traits] )
+and is equal to
+
Ch if specified,otherwise, quantity_ character:: scalar for the first signature, and otherwise, ( BC) . character ,
+where BC is the argument preceding Ch in the signatures above. is_ kind specifies
Q to start a new hierarchy tree of a kind
. Optional arguments may appear in any order
. [
Example 1 :
+inline constexpr struct length final : quantity_spec< dim_length> {
+} length;
+
+
+inline constexpr struct area final : quantity_spec< pow< 2 > ( length) > {
+} area;
+
+
+inline constexpr struct width final : quantity_spec< length> {
+} width;
+
+
+inline constexpr struct angular_measure final :
+ quantity_spec< dimensionless, arc_length / radius, is_kind> {
+} angular_measure;
+ —
end example ]
namespace mp_units {
+
+template < NamedQuantitySpec Q>
+using to-dimension = decltype ( auto ( Q:: dimension) ) ;
+
+template < typename . . . Expr>
+struct derived-quantity-spec-impl :
+ quantity-spec-interface ,
+ expr-fractions < struct dimensionless, Expr. . . > {
+ using base-type = derived-quantity-spec-impl ;
+ using base = expr-fractions < struct dimensionless, Expr. . . > ;
+
+ static constexpr Dimension auto dimension =
+ expr-map < to-dimension , derived_dimension, struct dimension_one> ( base { } ) ;
+ static constexpr quantity_character character = see below ;
+} ;
+
+template < SymbolicConstant . . . Expr>
+struct derived_quantity_spec final : derived-quantity-spec-impl < Expr. . . > { } ;
+
+}
+derived_ quantity_ spec is used by the library
+to represent the result of a quantity calculus not equal to a named quantity
. [
Example 1 :
constexpr auto area = pow< 2 > ( isq:: length) ;
+int x = area;
+ —
end example ]
+A program that instantiates a specialization of
derived_ quantity_ spec
+that is not a possible result of the library specifications
+is ill-formed, no diagnostic required
. Let
+
Nums and Dens
+be packs denoting the template arguments of
+base :: nums and base :: dens , respectively,QUANTITY-CHARACTER-OF ( Pack) be
+std:: max( { quantity_character:: scalar, expr-type < Pack> :: character. . . } )
+
+andnum_ char be QUANTITY-CHARACTER-OF ( Nums) and
+den_ char be QUANTITY-CHARACTER-OF ( Dens) .
+The member
character is equal to
+
quantity_ character:: scalar if
num_ char = = den_ char is
true , and
+
std:: max( num_ char, den_ char) otherwise
. namespace mp_units {
+
+struct dimensionless final : quantity_spec< derived_quantity_spec< > > { } ;
+
+}
+namespace mp_units {
+
+template < QuantitySpec Q>
+ requires ( ! QuantityKindSpec < Q> ) & & ( get-kind-tree-root ( Q{ } ) = = Q{ } )
+struct kind_of_ final : Q:: base-type {
+ using base-type = kind_of_;
+ static constexpr auto quantity-spec = Q{ } ;
+} ;
+
+}
+Effects : Equivalent to:
+
if constexpr ( ( . . . & & QuantityKindSpec < decltype ( From) > ) )
+ return kind_of< Q{ } > ;
+else
+ return q;
+template < QuantitySpec Q>
+consteval auto remove-kind ( Q q) ;
+
Effects : Equivalent to:
+
if constexpr ( QuantityKindSpec < Q> )
+ return Q:: quantity-spec ;
+else
+ return q;
+Effects : Equivalent to:
+if constexpr ( requires { requires get_quantity_spec( U{ } ) = = QS{ } ; } )
+ return u;
+else
+ return reference< QS, U> { } ;
+
namespace mp_units {
+
+struct quantity-spec-interface {
+ template < QuantitySpec Lhs, QuantitySpec Rhs>
+ friend consteval QuantitySpec auto operator * ( Lhs lhs, Rhs rhs) ;
+
+ template < QuantitySpec Lhs, QuantitySpec Rhs>
+ friend consteval QuantitySpec auto operator / ( Lhs lhs, Rhs rhs) ;
+
+ template < typename Self, UnitOf < Self{ } > U>
+ consteval Reference auto operator [ ] ( this Self self, U u) ;
+
+ template < typename Self, typename FwdQ, Quantity Q = std:: remove_cvref_t< FwdQ> >
+ requires QuantitySpecExplicitlyConvertibleTo < Q:: quantity_spec, Self{ } >
+ constexpr Quantity auto operator ( ) ( this Self self, FwdQ& & q) ;
+
+ template < QuantitySpec Lhs, QuantitySpec Rhs>
+ friend consteval bool operator = = ( Lhs, Rhs) ;
+} ;
+
+}
+Returns : clone-kind-of < Lhs{ } , Rhs{ } > ( expr-multiply < derived_quantity_spec, struct dimensionless> (
+ remove-kind ( lhs) , remove-kind ( rhs) ) )
+
Returns : clone-kind-of < Lhs{ } , Rhs{ } > ( expr-divide < derived_quantity_spec, struct dimensionless> (
+ remove-kind ( lhs) , remove-kind ( rhs) ) )
+
template < typename Self, UnitOf < Self{ } > U>
+consteval Reference auto operator [ ] ( this Self self, U u) ;
+
Returns :
make-reference ( self, u) . template < typename Self, typename FwdQ, Quantity Q = std:: remove_cvref_t< FwdQ> >
+ requires QuantitySpecExplicitlyConvertibleTo < Q:: quantity_spec, Self{ } >
+constexpr Quantity auto operator ( ) ( this Self self, FwdQ& & q) ;
+
Returns : quantity{ std:: forward< FwdQ> ( q) . numerical-value , make-reference ( self, Q:: unit) }
+
Returns :
std:: is_ same_ v< Lhs, Rhs> . Returns :
dimensionless / q . template < std:: intmax_t Num, std:: intmax_t Den = 1 , QuantitySpec Q>
+ requires ( Den ! = 0 )
+consteval QuantitySpec auto pow( Q q) ;
+
Returns : clone-kind-of < Q{ } > (
+ expr-pow < Num, Den, derived_quantity_spec, struct dimensionless> ( remove-kind ( q) ) ) ;
+
consteval bool implicitly_convertible( QuantitySpec auto from, QuantitySpec auto to) ;
+
consteval bool explicitly_convertible( QuantitySpec auto from, QuantitySpec auto to) ;
+
consteval bool castable( QuantitySpec auto from, QuantitySpec auto to) ;
+
consteval bool interconvertible( QuantitySpec auto qs1, QuantitySpec auto qs2) ;
+
Returns :
implicitly_ convertible( qs1, qs2) & & implicitly_ convertible( qs2, qs1) . Returns :
If
QuantityKindSpec < Q> is
true ,
+returns
remove-kind ( q) . Otherwise, if
+
is-derived-from-specialization-of < Q, quantity_ spec> ( )
+is
true , and
+the specialization of
Q:: quantity_ spec has a template argument equal to
is_ kind ,
+returns
q . Otherwise, if
Q:: parent is a valid expression,
+returns
get-kind-tree-root ( Q:: parent ) . Otherwise, if
DerivedQuantitySpec < Q> is
true ,
+returns
+
expr-map < to-kind , derived_quantity_spec, struct dimensionless> ( q)
+
+where
to-kind is defined as follows:
+
template < QuantitySpec Q>
+using to-kind = decltype ( get-kind-tree-root ( Q{ } ) ) ;
+template < QuantitySpec Q>
+consteval QuantityKindSpec auto get_kind( Q) ;
+
Returns :
kind_ of< get-kind-tree-root ( Q{ } ) > . Let
+
q1 be qs. . . [ 0 ] ,q2 be qs. . . [ 1 ] ,Q1 be decltype ( q1) ,Q2 be decltype ( q2) , andrest be a pack denoting the elements of qs without q1 and q2 . Effects : Equivalent to:
+
if constexpr ( sizeof . . . ( qs) = = 1 )
+ return q1;
+else if constexpr ( sizeof . . . ( qs) = = 2 ) {
+ using QQ1 = decltype ( remove-kind ( q1) ) ;
+ using QQ2 = decltype ( remove-kind ( q2) ) ;
+
+ if constexpr ( std:: is_same_v< Q1, Q2> )
+ return q1;
+ else if constexpr ( NestedQuantityKindSpecOf < Q1{ } , Q2{ } > )
+ return QQ1{ } ;
+ else if constexpr ( NestedQuantityKindSpecOf < Q2{ } , Q1{ } > )
+ return QQ2{ } ;
+ else if constexpr ( ( QuantityKindSpec < Q1> & & ! QuantityKindSpec < Q2> ) | |
+ ( DerivedQuantitySpec < QQ1> & & NamedQuantitySpec < QQ2> & &
+ implicitly_convertible( Q1{ } , Q2{ } ) ) )
+ return q2;
+ else if constexpr ( ( ! QuantityKindSpec < Q1> & & QuantityKindSpec < Q2> ) | |
+ ( NamedQuantitySpec < QQ1> & & DerivedQuantitySpec < QQ2> & &
+ implicitly_convertible( Q2{ } , Q1{ } ) ) )
+ return q1;
+ else if constexpr ( constexpr auto common_base = get-common-base < Q1{ } , Q2{ } > ( ) )
+ return * common_base;
+ else if constexpr ( implicitly_convertible( Q1{ } , Q2{ } ) )
+ return q2;
+ else if constexpr ( implicitly_convertible( Q2{ } , Q1{ } ) )
+ return q1;
+ else if constexpr ( implicitly_convertible( get-kind-tree-root ( Q1{ } ) ,
+ get-kind-tree-root ( Q2{ } ) ) )
+ return get-kind-tree-root ( q2) ;
+ else
+ return get-kind-tree-root ( q1) ;
+} else
+ return get_common_quantity_spec( get_common_quantity_spec( q1, q2) , rest. . . ) ;
+Remarks : The expression in the
requires-clause is equivalent to:
+
( sizeof . . . ( qs) ! = 0 & &
+ ( sizeof . . . ( qs) = = 1 | |
+ ( sizeof . . . ( qs) = = 2 & &
+ ( QuantitySpecConvertibleTo < get-kind-tree-root ( Q1{ } ) , get-kind-tree-root ( Q2{ } ) > | |
+ QuantitySpecConvertibleTo < get-kind-tree-root ( Q2{ } ) , get-kind-tree-root ( Q1{ } ) > ) ) | |
+ requires { get_common_quantity_spec( get_common_quantity_spec( q1, q2) , rest. . . ) ; } ) )
+Let
+
a s be the number of elements in h (A ) ,b s be the number of elements in h (B ) ,s be min ( a s , b s ) ,A be a tuple of the last s elements of h (A ) , andB be a tuple of the last s elements of h (B ). Effects : Looks for
x , the first pair-wise equal element in
A and
B . Returns :
std:: optional( x ) , if
x is found, and
std:: optional< unspecified > ( ) otherwise
. Returns : If
h (p ) has more elements than
h (ch ), returns
false . Otherwise, let
C be a tuple of the last
s elements of
h (ch ),
+where
s is the number of elements in
h (p ). template < typename T>
+concept MagConstant = SymbolicConstant < T> & & is-derived-from-specialization-of < T, mag_constant> ( ) ;
+
+template < typename T>
+concept UnitMagnitude = ( is-specialization-of < T, unit-magnitude > ( ) ) ;
+
+template < typename T>
+concept MagArg = std:: integral< T> | | MagConstant < T> ;
+
namespace mp_units {
+
+template < symbol_text Symbol, long double Value>
+ requires ( Value > 0 )
+struct mag_constant {
+ static constexpr auto symbol = Symbol;
+ static constexpr long double value = Value;
+} ;
+
+}
+ Symbol is its symbol, and
+
Value is (an approximation of) its value
. namespace mp_units {
+
+template < auto . . . Ms>
+struct unit-magnitude {
+
+
+ template < UnitMagnitude M>
+ friend consteval UnitMagnitude auto operator * ( unit-magnitude lhs, M rhs) ;
+
+ friend consteval auto operator / ( unit-magnitude lhs, UnitMagnitude auto rhs) ;
+
+ template < UnitMagnitude Rhs>
+ friend consteval bool operator = = ( unit-magnitude , Rhs) ;
+
+ template < int Num, int Den = 1 >
+ friend consteval auto pow ( unit-magnitude ) ;
+
+
+
+ friend consteval bool is-positive-integral-power ( unit-magnitude ) ;
+
+ template < auto . . . Ms2>
+ friend consteval auto common-magnitude ( unit-magnitude ,
+ unit-magnitude < Ms2. . . > ) ;
+} ;
+
+}
+A specialization of
unit-magnitude
+represents the product of its template arguments
. For the purposes of specifying the implementation-defined limits,
+let the representation of the terms of
unit-magnitude be the structure
+
struct {
+ ratio exp;
+ base-type base;
+} ;
+
+representing the number
base exp ,
+where
base-type is a model of
MagArg . There is a single term for each
base-type . exp. num is not expanded into base
. exp. den can reduce the base
. If the result of an operation on
std:: intmax_ t values is undefined,
+the behavior is
+
implementation-defined
. Returns :
If
sizeof . . . ( Ms) = = 0 is
true , returns
rhs . Otherwise, if
std:: is_ same_ v< M, unit-magnitude < > > , returns
lhs . Otherwise, returns an unspecified value equal to
lhs ×rhs . friend consteval auto operator / ( unit-magnitude lhs, UnitMagnitude auto rhs) ;
+
Returns :
lhs * pow < - 1 > ( rhs) . template < UnitMagnitude Rhs>
+friend consteval bool operator = = ( unit-magnitude , Rhs) ;
+
Returns :
std:: is_ same_ v< unit-magnitude , Rhs> . template < int Num, int Den = 1 >
+friend consteval auto pow ( unit-magnitude base) ;
+
Returns :
If
Num = = 0 is
true , returns
unit-magnitude < > { } . Otherwise, returns an unspecified value equal to
base Num / Den . template < MagArg auto V>
+constexpr UnitMagnitude auto mag = see below ;
+
Constraints :
V is greater than
0 . Effects : If
MagConstant < decltype ( V) > is satisfied,
+initializes
mag with
unit-magnitude < V> { } . Otherwise, initializes
mag with
+an unspecified value equal to
V . template < std:: intmax_t N, std:: intmax_t D>
+ requires ( N > 0 )
+constexpr UnitMagnitude auto mag_ratio = see below ;
+
Effects : Initializes
mag_ ratio with
+an unspecified value equal to
N / D . template < MagArg auto Base, int Num, int Den = 1 >
+constexpr UnitMagnitude auto mag_power = pow < Num, Den> ( mag< Base> ) ;
+
Constraints :
Base is greater than
0 . friend consteval bool is-positive-integral-power ( unit-magnitude x) ;
+
Returns :
false if
x has a negative or rational exponent, and
+
true otherwise
. template < auto . . . Ms2>
+friend consteval auto common-magnitude ( unit-magnitude , unit-magnitude < Ms2. . . > ) ;
+
Returns : The largest magnitude
C
+such that each input magnitude is expressible
+by only positive powers relative to
C . template < Unit auto U>
+constexpr bool space_before_unit_symbol = true ;
+
The formatting functions (
[qty. unit. sym. fmt] ) use
space_ before_ unit_ symbol
+to determine whether there is a space
+between the numerical value and the unit symbol
. Such specializations shall be usable in constant expressions (
N4971, [expr.const] )
+and have type
const bool . template < typename T>
+concept Unit = SymbolicConstant < T> & & std:: derived_from< T, unit-interface > ;
+
+template < typename T>
+concept PrefixableUnit = Unit < T> & & is-derived-from-specialization-of < T, named_unit> ( ) ;
+
+template < typename T>
+concept AssociatedUnit = Unit < U> & & has-associated-quantity ( U{ } ) ;
+
+template < typename U, auto QS>
+concept UnitOf = AssociatedUnit < U> & & QuantitySpec < decltype ( QS) > & &
+ QuantitySpecConvertibleTo < get_quantity_spec( U{ } ) , QS> & &
+ ( get_kind( QS) = = get_kind( get_quantity_spec( U{ } ) ) | |
+ ! NestedQuantityKindSpecOf < get_quantity_spec( U{ } ) , QS> ) ;
+
+template < auto From, auto To>
+concept UnitConvertibleTo =
+ Unit < decltype ( From) > & & Unit < decltype ( To) > & & ( convertible( From, To) ) ;
+
+template < typename U, auto FromU, auto QS>
+concept UnitCompatibleWith =
+ Unit < U> & & Unit < decltype ( FromU) > & & QuantitySpec < decltype ( QS) > & &
+ ( ! AssociatedUnit < U> | | UnitOf < U, QS> ) & & UnitConvertibleTo < FromU, U{ } > ;
+
+template < typename T>
+concept OffsetUnit = Unit < T> & & requires { T:: point-origin ; } ;
+
+template < typename From, typename To>
+concept PotentiallyConvertibleTo =
+ Unit < From> & & Unit < To> & &
+ ( ( AssociatedUnit < From> & & AssociatedUnit < To> & &
+ implicitly_convertible( get_quantity_spec( From{ } ) , get_quantity_spec( To{ } ) ) ) | |
+ ( ! AssociatedUnit < From> & & ! AssociatedUnit < To> ) ) ;
+
namespace mp_units {
+
+template < UnitMagnitude M, Unit U>
+struct canonical-unit {
+ M mag;
+ U reference_unit;
+} ;
+
+}
+ [
Note 1 :
Other types representing units are equal only if they have the same type
. canonical-unit is used to implement binary relations other than equality
. —
end note ]
consteval auto get-canonical-unit ( Unit auto u) ;
+
Returns : The instantiation of
canonical-unit for
u . namespace mp_units {
+
+template < UnitMagnitude auto M, Unit U>
+ requires ( M ! = unit-magnitude < > { } & & M ! = mag< 1 > )
+struct scaled_unit final : unit-interface {
+ using base-type = scaled_unit;
+ static constexpr UnitMagnitude auto mag = M;
+ static constexpr U reference-unit { } ;
+ static constexpr auto point-origin = U:: point_origin;
+
+} ;
+
+}
+scaled_ unit< M, U> is used by the library
+to represent the unit
M ×U . namespace mp_units {
+
+template < symbol_text Symbol, QuantityKindSpec auto QS>
+ requires ( ! Symbol. empty( ) ) & & BaseDimension < decltype ( auto ( QS. dimension) ) >
+struct named_unit< Symbol, QS> : unit-interface {
+ using base-type = named_unit;
+ static constexpr auto symbol = Symbol;
+ static constexpr auto quantity-spec = QS;
+} ;
+
+template < symbol_text Symbol, QuantityKindSpec auto QS, PointOrigin auto PO>
+ requires ( ! Symbol. empty( ) ) & & BaseDimension < decltype ( auto ( QS. dimension) ) >
+struct named_unit< Symbol, QS, PO> : unit-interface {
+ using base-type = named_unit;
+ static constexpr auto symbol = Symbol;
+ static constexpr auto quantity-spec = QS;
+ static constexpr auto point-origin = PO;
+} ;
+
+template < symbol_text Symbol>
+ requires ( ! Symbol. empty( ) )
+struct named_unit< Symbol> : unit-interface {
+ using base-type = named_unit;
+ static constexpr auto symbol = Symbol;
+} ;
+
+template < symbol_text Symbol, Unit auto U>
+ requires ( ! Symbol. empty( ) )
+struct named_unit< Symbol, U> : decltype ( U) :: base-type {
+ using base-type = named_unit;
+ static constexpr auto symbol = Symbol;
+} ;
+
+template < symbol_text Symbol, Unit auto U, PointOrigin auto PO>
+ requires ( ! Symbol. empty( ) )
+struct named_unit< Symbol, U, PO> : decltype ( U) :: base-type {
+ using base-type = named_unit;
+ static constexpr auto symbol = Symbol;
+ static constexpr auto point-origin = PO;
+} ;
+
+template < symbol_text Symbol, AssociatedUnit auto U, QuantityKindSpec auto QS>
+ requires ( ! Symbol. empty( ) ) & & ( QS. dimension = = get-associated-quantity ( U) . dimension)
+struct named_unit< Symbol, U, QS> : decltype ( U) :: base-type {
+ using base-type = named_unit;
+ static constexpr auto symbol = Symbol;
+ static constexpr auto quantity-spec = QS;
+} ;
+
+template < symbol_text Symbol, AssociatedUnit auto U, QuantityKindSpec auto QS,
+ PointOrigin auto PO>
+ requires ( ! Symbol. empty( ) ) & & ( QS. dimension = = get-associated-quantity ( U) . dimension)
+struct named_unit< Symbol, U, QS, PO> : decltype ( U) :: base-type {
+ using base-type = named_unit;
+ static constexpr auto symbol = Symbol;
+ static constexpr auto quantity-spec = QS;
+ static constexpr auto point-origin = PO;
+} ;
+
+}
+ A specialization of
named_ unit is used as a base type when defining a named unit
. In the following descriptions, let
U be a named unit defined with an alluded signature
. The possible arguments to
named_ unit are
+
( the unit symbol , a kind of base quantity , a point origin o p t ) ,( the unit symbol ) ,( the unit symbol , a unit expression , a point origin o p t ) , and( the unit symbol , a unit expression , a kind of quantity , a point origin o p t ) . The second signature defines a unit
+that can be reused by several base quantities
. The third and fourth signatures with a unit expression argument
E
+define
U as implicitly convertible from
E . A point origin argument specifies the default point origin of
U (
[qty. pt. syn] )
. [
Example 1 :
+inline constexpr struct second final : named_unit< "s" , kind_of< time> > {
+} second;
+
+
+inline constexpr struct minute final : named_unit< "min" , mag< 60 > * second> {
+} minute;
+
+
+inline constexpr struct hertz final : named_unit< "Hz" , inverse( second) , kind_of< frequency> > {
+} hertz;
+
+
+ —
end example ]
namespace mp_units {
+
+template < symbol_text Symbol, UnitMagnitude auto M, PrefixableUnit auto U>
+ requires ( ! Symbol. empty( ) )
+struct prefixed_unit : decltype ( M * U) :: base-type {
+ using base-type = prefixed_unit;
+ static constexpr auto symbol = Symbol + U. symbol ;
+} ;
+
+}
+ Symbol is the symbol of the unit prefix
. M is the factor of the unit prefix
. A specialization of
prefixed_ unit is used as a base type when defining a unit prefix
. [
Example 1 :
template < PrefixableUnit auto U>
+struct kilo_ : prefixed_unit< "k" , mag_power< 10 , 3 > , U> { } ;
+
+template < PrefixableUnit auto U>
+constexpr kilo_< U> kilo;
+
+inline constexpr auto kilogram = kilo< si:: gram> ;
+ —
end example ]
namespace mp_units {
+
+template < Unit U1, Unit U2, Unit . . . Rest>
+struct common_unit final : decltype ( get-common-scaled-unit ( U1{ } , U2{ } , Rest{ } . . . ) ) :: base-type
+{
+ using base-type = common_unit;
+ static constexpr auto common-unit =
+ get-common-scaled-unit ( U1{ } , U2{ } , Rest{ } . . . ) ;
+} ;
+
+}
+common_ unit is used by the library
+to encapsulate a conversion factor between units (
IEC 60050, 112-01-33 )
+common to the operands of quantity addition
. [
Example 1 :
The result of
1 * km + 1 * mi
+has a common unit
[ 8 / 125 ] Â m
+encapsulated by
common_ unit< mi, km> . —
end example ]
+A program that instantiates a specialization of
common_ unit
+that is not a possible result of the library specifications
+is ill-formed, no diagnostic required
. template < Unit U1, Unit U2, Unit . . . Rest>
+consteval Unit auto get-common-scaled-unit ( U1, U2, Rest. . . rest)
+ requires see below ;
+
Effects : Equivalent to:
+constexpr auto res = [ ] {
+ constexpr auto canonical_lhs = get-canonical-unit ( U1{ } ) ;
+ constexpr auto canonical_rhs = get-canonical-unit ( U2{ } ) ;
+ constexpr auto common_mag = common-magnitude ( canonical_lhs. mag, canonical_rhs. mag) ;
+ if constexpr ( common_mag = = mag< 1 > )
+ return canonical_lhs. reference_unit;
+ else
+ return scaled_unit< common_mag, decltype ( auto ( canonical_lhs. reference_unit) ) > { } ;
+} ( ) ;
+if constexpr ( sizeof . . . ( rest) = = 0 )
+ return res;
+else
+ return get-common-scaled-unit ( res, rest. . . ) ;
+
Remarks : The expression in the requires-clause is equivalent to:
+( convertible( U1{ } , U2{ } ) & & ( sizeof . . . ( Rest) = = 0 | | requires {
+ get-common-scaled-unit ( get-common-scaled-unit ( u1, u2) , rest. . . ) ;
+ } ) )
+
namespace mp_units {
+
+template < typename . . . Expr>
+struct derived-unit-impl :
+ unit-interface ,
+ expr-fractions < struct one, Expr. . . > {
+ using base-type = derived-unit-impl ;
+} ;
+
+template < SymbolicConstant . . . Expr>
+struct derived_unit final : derived-unit-impl < Expr. . . > { } ;
+
+}
+ [
Example 1 :
using namespace si:: unit_symbols;
+int x = m * m;
+int y = m * s;
+int z = m / s;
+ —
end example ]
+A program that instantiates a specialization of
derived_ unit
+that is not a possible result of the library specifications
+is ill-formed, no diagnostic required
. namespace mp_units {
+
+struct one final : derived-unit-impl < > { } ;
+
+}
+namespace mp_units {
+
+struct unit-interface {
+ template < UnitMagnitude M, Unit U>
+ friend consteval Unit auto operator * ( M, U u) ;
+
+ friend consteval Unit auto operator * ( Unit auto , UnitMagnitude auto ) = delete ;
+
+ template < UnitMagnitude M, Unit U>
+ friend consteval Unit auto operator / ( M mag, U u) ;
+
+ template < Unit Lhs, Unit Rhs>
+ friend consteval Unit auto operator * ( Lhs lhs, Rhs rhs) ;
+
+ template < Unit Lhs, Unit Rhs>
+ friend consteval Unit auto operator / ( Lhs lhs, Rhs rhs) ;
+
+
+
+ template < Unit Lhs, Unit Rhs>
+ friend consteval bool operator = = ( Lhs, Rhs) ;
+
+ template < Unit Lhs, Unit Rhs>
+ friend consteval bool equivalent( Lhs lhs, Rhs rhs) ;
+} ;
+
+}
+Effects : Equivalent to:
+if constexpr ( std:: is_same_v< M, decltype ( auto ( mag< 1 > ) ) > )
+ return u;
+else if constexpr ( is-specialization-of < U, scaled_unit> ( ) ) {
+ if constexpr ( M{ } * U:: mag = = mag< 1 > )
+ return U:: reference-unit ;
+ else
+ return scaled_unit< M{ } * U:: mag , decltype ( auto ( U:: reference-unit ) ) > { } ;
+} else
+ return scaled_unit< M{ } , U> { } ;
+
Recommended practice : Suggest swapping the operands
. Returns :
mag * inverse( u) . template < Unit Lhs, Unit Rhs>
+friend consteval Unit auto operator * ( Lhs lhs, Rhs rhs) ;
+
Returns :
expr-multiply < derived_ unit, struct one> ( lhs, rhs) . template < Unit Lhs, Unit Rhs>
+friend consteval Unit auto operator / ( Lhs lhs, Rhs rhs) ;
+
Returns :
expr-divide < derived_ unit, struct one> ( lhs, rhs) . consteval Unit auto inverse( Unit auto u) ;
+
template < std:: intmax_t Num, std:: intmax_t Den = 1 , Unit U>
+ requires ( Den ! = 0 )
+consteval Unit auto pow( U u) ;
+
Returns :
expr-pow < Num, Den, derived_ unit, struct one> ( u) . consteval Unit auto sqrt( Unit auto u) ;
+
consteval Unit auto cbrt( Unit auto u) ;
+
consteval Unit auto square( Unit auto u) ;
+
consteval Unit auto cubic( Unit auto u) ;
+
template < Unit Lhs, Unit Rhs>
+friend consteval bool operator = = ( Lhs, Rhs) ;
+
Returns :
std:: is_ same_ v< Lhs, Rhs> . template < Unit Lhs, Unit Rhs>
+friend consteval bool equivalent( Lhs lhs, Rhs rhs) ;
+
Effects : Equivalent to:
+const auto lhs_canonical = get-canonical-unit ( lhs) ;
+const auto rhs_canonical = get-canonical-unit ( rhs) ;
+return lhs_canonical. mag = = rhs_canonical. mag & &
+ lhs_canonical. reference_unit = = rhs_canonical. reference_unit;
+
template < Unit From, Unit To>
+consteval bool convertible( From from, To to) ;
+
Effects : Equivalent to:
+
if constexpr ( std:: is_same_v< From, To> )
+ return true ;
+else if constexpr ( PotentiallyConvertibleTo < From, To> )
+ return std:: is_same_v< decltype ( get-canonical-unit ( from) . reference_unit) ,
+ decltype ( get-canonical-unit ( to) . reference_unit) > ;
+else
+ return false ;
+Returns :
kind_ of< get-associated-quantity ( u) > . consteval Unit auto get_common_unit( Unit auto . . . us)
+ requires see below ;
+
Let
+
u1 be us. . . [ 0 ] ,u2 be us. . . [ 1 ] ,U1 be decltype ( u1) ,U2 be decltype ( u2) , andrest be a pack denoting the elements of us without u1 and u2 . Effects : Equivalent to:
+if constexpr ( sizeof . . . ( us) = = 1 )
+ return u1;
+else if constexpr ( sizeof . . . ( us) = = 2 ) {
+ if constexpr ( is-derived-from-specialization-of < U1, common_unit> ( ) ) {
+ return TBD. ;
+ } else if constexpr ( is-derived-from-specialization-of < U2, common_unit> ( ) )
+ return get_common_unit( u2, u1) ;
+ else if constexpr ( std:: is_same_v< U1, U2> )
+ return u1;
+ else if constexpr ( equivalent( U1{ } , U2{ } ) ) {
+ if constexpr ( std:: derived_from< U1, typename U2:: base-type > )
+ return u1;
+ else if constexpr ( std:: derived_from< U2, typename U1:: base-type > )
+ return u2;
+ else
+ return std:: conditional_t< type-less-impl < U1, U2> ( ) , U1, U2> { } ;
+ } else {
+ constexpr auto canonical_lhs = get-canonical-unit ( U1{ } ) ;
+ constexpr auto canonical_rhs = get-canonical-unit ( U2{ } ) ;
+
+ if constexpr ( is-positive-integral-power ( canonical_lhs. mag / canonical_rhs. mag) )
+ return u2;
+ else if constexpr ( is-positive-integral-power ( canonical_rhs. mag / canonical_lhs. mag) )
+ return u1;
+ else {
+ if constexpr ( type-less < U1, U2> { } )
+ return common_unit< U1, U2> { } ;
+ else
+ return common_unit< U2, U1> { } ;
+ }
+ }
+} else
+ return get_common_unit( get_common_unit( u1, u2) , rest. . . ) ;
+
Remarks : The expression in the requires-clause is equivalent to:
+( sizeof . . . ( us) ! = 0 & & ( sizeof . . . ( us) = = 1 | |
+ ( sizeof . . . ( us) = = 2 & & convertible( U1{ } , U2{ } ) ) | |
+ requires { get_common_unit( get_common_unit( u1, u2) , rest. . . ) ; } ) )
+
template < Unit U>
+consteval bool has-associated-quantity ( U) ;
+
Returns :
If
U:: quantity-spec is a valid expression,
+returns
true . Otherwise, if U:: reference-unit is a valid expression,
+returns
+has-associated-quantity ( U:: reference-unit )
+
Otherwise, if
+
is-derived-from-specialization-of < U, expr-fractions > ( )
+is
true ,
+let
Nums and
Dens
+be packs denoting the template arguments of
+
U:: nums and
U:: dens , respectively
. Returns
+( . . . & & has-associated-quantity ( expr-type < Nums> { } ) ) & &
+ ( . . . & & has-associated-quantity ( expr-type < Dens> { } ) )
+
Otherwise, returns
false . template < AssociatedUnit U>
+consteval auto get-associated-quantity ( U u) ;
+
Returns :
If U is of the form common_ unit< Us. . . > ,
+returns
+get_common_quantity_spec( get-associated-quantity ( Us{ } ) . . . )
+ Otherwise, if U:: quantity-spec is a valid expression,
+returns
+remove-kind ( U:: quantity-spec )
+ Otherwise, if U:: reference-unit is a valid expression,
+returns
+get-associated-quantity ( U:: reference-unit )
+ Otherwise, if
+is-derived-from-specialization-of < U, expr-fractions > ( )
+is true ,
+returns
+expr-map < to-quantity-spec , derived_quantity_spec, struct dimensionless> ( u)
+
+where to-quantity-spec is defined as follows:
+template < AssociatedUnit U>
+using to-quantity-spec = decltype ( get-associated-quantity ( U{ } ) ) ;
+ template < typename CharT = char , std:: output_iterator< CharT> Out, Unit U>
+constexpr Out unit_symbol_to( Out out, U u, const unit_symbol_formatting& fmt = { } ) ;
+
template < unit_symbol_formatting fmt = { } , typename CharT = char , Unit U>
+consteval std:: string_view unit_symbol( U) ;
+
Effects : Equivalent to:
+TBD.
+
namespace mp_units {
+
+template < QuantitySpec auto Q, Unit auto U>
+using reference-t = reference< decltype ( Q) , decltype ( U) > ;
+
+template < QuantitySpec Q, Unit U>
+struct reference {
+
+
+ template < typename Q2, typename U2>
+ friend consteval auto operator * ( reference, reference< Q2, U2> )
+ - > reference-t < Q{ } * Q2{ } , U{ } * U2{ } > ;
+
+ template < AssociatedUnit U2>
+ friend consteval auto operator * ( reference, U2)
+ - > reference-t < Q{ } * get_quantity_spec( U2{ } ) , U{ } * U2{ } > ;
+
+ template < AssociatedUnit U1>
+ friend consteval auto operator * ( U1, reference)
+ - > reference-t < get_quantity_spec( U1{ } ) * Q{ } , U1{ } * U{ } > ;
+
+ template < typename Q2, typename U2>
+ friend consteval auto operator / ( reference, reference< Q2, U2> )
+ - > reference-t < Q{ } / Q2{ } , U{ } / U2{ } > ;
+
+ template < AssociatedUnit U2>
+ friend consteval auto operator / ( reference, U2)
+ - > reference-t < Q{ } / get_quantity_spec( U2{ } ) , U{ } / U2{ } > ;
+
+ template < AssociatedUnit U1>
+ friend consteval auto operator / ( U1, reference)
+ - > reference-t < get_quantity_spec( U1{ } ) / Q{ } , U1{ } / U{ } > ;
+
+ friend consteval auto inverse( reference) - > reference-t < inverse( Q{ } ) , inverse( U{ } ) > ;
+
+ template < std:: intmax_t Num, std:: intmax_t Den = 1 >
+ requires ( Den ! = 0 )
+ friend consteval auto pow( reference) - > reference-t < pow< Num, Den> ( Q{ } ) , pow< Num, Den> ( U{ } ) > ;
+ friend consteval auto sqrt( reference) - > reference-t < sqrt( Q{ } ) , sqrt( U{ } ) > ;
+ friend consteval auto cbrt( reference) - > reference-t < cbrt( Q{ } ) , cbrt( U{ } ) > ;
+
+
+
+ template < typename Q2, typename U2>
+ friend consteval bool operator = = ( reference, reference< Q2, U2> ) ;
+
+ template < AssociatedUnit U2>
+ friend consteval bool operator = = ( reference, U2 u2) ;
+
+ template < typename Q2, typename U2>
+ friend consteval bool convertible( reference, reference< Q2, U2> ) ;
+
+ template < AssociatedUnit U2>
+ friend consteval bool convertible( reference, U2 u2) ;
+
+ template < AssociatedUnit U1>
+ friend consteval bool convertible( U1 u1, reference) ;
+} ;
+
+}
+ [
Note 1 :
reference is typically implicitly instantiated
+when specifying that a unit measures a more specific quantity
. [
Example 1 :
using namespace si:: unit_symbols;
+auto x = 1 * m;
+auto y = 1 * isq:: width[ m] ;
+auto z = 1 * isq:: diameter[ m] ;
+ —
end example ]
—
end note ]
Each member function with a
trailing-return-type
+of
- > reference-t < T. . . >
+returns
{ } . template < typename FwdRep, Reference R,
+ RepresentationOf < get_quantity_spec( R{ } ) > Rep = std:: remove_cvref_t< FwdRep> >
+ requires ( ! OffsetUnit < decltype ( get_unit( R{ } ) ) > )
+constexpr quantity< R{ } , Rep> operator * ( FwdRep& & lhs, R r) ;
+
Effects : Equivalent to:
+return quantity{ std:: forward< FwdRep> ( lhs) , r} ;
template < typename FwdRep, Reference R,
+ RepresentationOf < get_quantity_spec( R{ } ) > Rep = std:: remove_cvref_t< FwdRep> >
+ requires ( ! OffsetUnit < decltype ( get_unit( R{ } ) ) > )
+constexpr Quantity auto operator / ( FwdRep& & lhs, R) ;
+
Effects : Equivalent to:
+return quantity{ std:: forward< FwdRep> ( lhs) , inverse( R{ } ) } ;
template < typename FwdQ, Reference R, Quantity Q = std:: remove_cvref_t< FwdQ> >
+constexpr Quantity auto operator * ( FwdQ& & q, R) ;
+template < typename FwdQ, Reference R, Quantity Q = std:: remove_cvref_t< FwdQ> >
+constexpr Quantity auto operator / ( FwdQ& & q, R) ;
+
Effects : Equivalent to:
+return quantity{ std:: forward< FwdQ> ( q) . numerical-value , Q:: reference @ R{ } } ;
+
template < Reference R, typename Rep>
+ requires RepresentationOf < std:: remove_cvref_t< Rep> , get_quantity_spec( R{ } ) >
+constexpr auto operator * ( R, Rep& & ) = delete ;
+
+template < Reference R, typename Rep>
+ requires RepresentationOf < std:: remove_cvref_t< Rep> , get_quantity_spec( R{ } ) >
+constexpr auto operator / ( R, Rep& & ) = delete ;
+
+template < Reference R, typename Q>
+ requires Quantity < std:: remove_cvref_t< Q> >
+constexpr auto operator * ( R, Q& & ) = delete ;
+
+template < Reference R, typename Q>
+ requires Quantity < std:: remove_cvref_t< Q> >
+constexpr auto operator / ( R, Q& & ) = delete ;
+
Recommended practice : Suggest swapping the operands
. template < typename Q2, typename U2>
+friend consteval bool operator = = ( reference, reference< Q2, U2> ) ;
+
Returns :
Q{ } = = Q2{ } & & U{ } = = U2{ } . template < AssociatedUnit U2>
+friend consteval bool operator = = ( reference, U2 u2) ;
+
Returns :
Q{ } = = get_ quantity_ spec( u2) & & U{ } = = u2 . template < typename Q2, typename U2>
+friend consteval bool convertible( reference, reference< Q2, U2> ) ;
+
Returns :
implicitly_ convertible( Q{ } , Q2{ } ) & & convertible( U{ } , U2{ } ) . template < AssociatedUnit U2>
+friend consteval bool convertible( reference, U2 u2) ;
+
Returns :
implicitly_ convertible( Q{ } , get_ quantity_ spec( u2) ) & & convertible( U{ } , u2) . template < AssociatedUnit U1>
+friend consteval bool convertible( U1 u1, reference) ;
+
Returns :
implicitly_ convertible( get_ quantity_ spec( u1) , Q{ } ) & & convertible( u1, U{ } ) . template < typename Q, typename U>
+consteval QuantitySpec auto get_quantity_spec( reference< Q, U> ) ;
+
template < typename Q, typename U>
+consteval Unit auto get_unit( reference< Q, U> ) ;
+
Returns :
get_ common_ unit( u1, u2, rest. . . ) . Remarks : The expression in the requires-clause is equivalent to:
+requires {
+ get_common_quantity_spec( get_quantity_spec( u1) , get_quantity_spec( u2) ,
+ get_quantity_spec( rest) . . . ) ;
+ { get_common_unit( u1, u2, rest. . . ) } - > AssociatedUnit;
+}
+
Returns : reference-t < 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) . . . ) > { } ;
+
Remarks : The expression in the requires-clause is equivalent to:
+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) . . . ) ;
+}
+
template < typename T>
+struct actual-value-type : cond-value-type < T> { } ;
+
+template < typename T>
+ requires ( ! std:: is_pointer_v< T> & & ! std:: is_array_v< T> ) & &
+ requires { typename std:: indirectly_readable_traits< T> :: value_type; }
+struct actual-value-type < T> : std:: indirectly_readable_traits< T> { } ;
+
+template < typename T>
+using actual-value-type-t = actual-value-type < T> :: value_type;
+
+template < typename Rep>
+constexpr bool treat_as_floating_point =
+ std:: chrono:: treat_as_floating_point_v< actual-value-type-t < Rep> > ;
+
quantity and
quantity_ point use
treat_ as_ floating_ point
+to help determine whether implicit conversions are allowed among them
. Such specializations shall be usable in constant expressions (
N4971, [expr.const] )
+and have type
const bool . template < typename T>
+constexpr bool disable_scalar = false ;
+template < typename T>
+constexpr bool disable_complex = false ;
+template < typename T>
+constexpr bool disable_vector = false ;
+
The representation concepts use these traits
+to help determine the sets
T represents
. Such specializations shall be usable in constant expressions (
N4971, [expr.const] )
+and have type
const bool . [
Note 1 :
These templates prevent use of representation types with the library
+that satisfy but do not in fact model their corresponding concept
. —
end note ]
quantity and
quantity_ point use
representation_ values
+to construct special values of its representation type
. namespace mp_units {
+
+template < typename Rep>
+struct representation_values : std:: chrono:: duration_values< Rep> {
+ static constexpr Rep one( ) noexcept ;
+} ;
+
+}
+static constexpr Rep one( ) noexcept ;
+
Given a subexpression
E with type
T ,
+let
t be an lvalue that denotes the reified object for
E . Then:
+
If
T does not model
WeaklyRegular ,
+
mp_ units:: real( E) is ill-formed
. If
auto ( t. real( ) ) is a valid expression whose type models
Scalar ,
+
mp_ units:: real( E) is expression-equivalent to
auto ( t. real( ) ) . Otherwise, if
T is a class or enumeration type and
+
auto ( real( t) ) is a valid expression whose type models
Scalar
+where the meaning of
real is established as-if by performing argument-dependent lookup only (
N4971, [basic.lookup.argdep] ),
+then
mp_ units:: real( E) is expression-equivalent to that expression
. Otherwise,
mp_ units:: real( E) is ill-formed
. Given a subexpression
E with type
T ,
+let
t be an lvalue that denotes the reified object for
E . Then:
+
If
T does not model
WeaklyRegular ,
+
mp_ units:: imag( E) is ill-formed
. If
auto ( t. imag( ) ) is a valid expression whose type models
Scalar ,
+
mp_ units:: imag( E) is expression-equivalent to
auto ( t. imag( ) ) . Otherwise, if
T is a class or enumeration type and
+
auto ( imag( t) ) is a valid expression whose type models
Scalar
+where the meaning of
imag is established as-if by performing argument-dependent lookup only (
N4971, [basic.lookup.argdep] ),
+then
mp_ units:: imag( E) is expression-equivalent to that expression
. Otherwise,
mp_ units:: imag( E) is ill-formed
. Given a subexpression
E with type
T ,
+let
t be an lvalue that denotes the reified object for
E . Then:
+
If
T does not model
WeaklyRegular ,
+
mp_ units:: modulus( E) is ill-formed
. If
auto ( t. modulus( ) ) is a valid expression whose type models
Scalar ,
+
mp_ units:: modulus( E) is expression-equivalent to
auto ( t. modulus( ) ) . Otherwise, if
T is a class or enumeration type and
+
auto ( modulus( t) ) is a valid expression whose type models
Scalar
+where the meaning of
modulus is established as-if by performing argument-dependent lookup only (
N4971, [basic.lookup.argdep] ),
+then
mp_ units:: modulus( E) is expression-equivalent to that expression
. If
auto ( t. abs( ) ) is a valid expression whose type models
Scalar ,
+
mp_ units:: modulus( E) is expression-equivalent to
auto ( t. abs( ) ) . Otherwise, if
T is a class or enumeration type and
+
auto ( abs( t) ) is a valid expression whose type models
Scalar
+where the meaning of
abs is established as-if by performing argument-dependent lookup only (
N4971, [basic.lookup.argdep] ),
+then
mp_ units:: modulus( E) is expression-equivalent to that expression
. Otherwise,
mp_ units:: modulus( E) is ill-formed
. Given a subexpression
E with type
T ,
+let
t be an lvalue that denotes the reified object for
E . Then:
+
If
T does not model
WeaklyRegular ,
+
mp_ units:: magnitude( E) is ill-formed
. If
auto ( t. magnitude( ) ) is a valid expression whose type models
Scalar ,
+
mp_ units:: magnitude( E) is expression-equivalent to
auto ( t. magnitude( ) ) . Otherwise, if
T is a class or enumeration type and
+
auto ( magnitude( t) ) is a valid expression whose type models
Scalar
+where the meaning of
magnitude is established as-if by performing argument-dependent lookup only (
N4971, [basic.lookup.argdep] ),
+then
mp_ units:: magnitude( E) is expression-equivalent to that expression
. Otherwise, if
auto ( t. abs( ) ) is a valid expression whose type models
Scalar ,
+
mp_ units:: magnitude( E) is expression-equivalent to
auto ( t. abs( ) ) . Otherwise, if
T is a class or enumeration type and
+
auto ( abs( t) ) is a valid expression whose type models
Scalar
+where the meaning of
magnitude is established as-if by performing argument-dependent lookup only (
N4971, [basic.lookup.argdep] ),
+then
mp_ units:: magnitude( E) is expression-equivalent to that expression
. Otherwise,
mp_ units:: magnitude( E) is ill-formed
. template < typename T>
+concept WeaklyRegular = std:: copyable< T> & & std:: equality_comparable< T> ;
+
+template < typename T>
+concept Scalar = ( ! disable_scalar< T> ) & & WeaklyRegular < T> & & requires ( T a, T b) {
+
+ { - a } - > std:: common_with< T> ;
+ { a + b } - > std:: common_with< T> ;
+ { a - b } - > std:: common_with< T> ;
+ { a * b } - > std:: common_with< T> ;
+ { a / b } - > std:: common_with< T> ;
+} ;
+
template < typename T>
+using value-type-t = actual-value-type-t < T> ;
+
+template < typename T>
+concept Complex =
+ ( ! disable_complex< T> ) & & WeaklyRegular < T> & & Scalar < value-type-t < T> > & &
+ std:: constructible_from< T, value-type-t < T> , value-type-t < T> > & &
+ requires ( T a, T b, value-type-t < T> s) {
+
+ { - a } - > std:: common_with< T> ;
+ { a + b } - > std:: common_with< T> ;
+ { a - b } - > std:: common_with< T> ;
+ { a * b } - > std:: common_with< T> ;
+ { a / b } - > std:: common_with< T> ;
+ { a * s } - > std:: common_with< T> ;
+ { s * a } - > std:: common_with< T> ;
+ { a / s } - > std:: common_with< T> ;
+ :: mp_units:: real( a) ;
+ :: mp_units:: imag( a) ;
+ :: mp_units:: modulus( a) ;
+ } ;
+
template < typename T>
+concept Vector =
+ ( ! disable_vector< T> ) & & WeaklyRegular < T> & & Scalar < value-type-t < T> > & &
+ requires ( T a, T b, value-type-t < T> s) {
+
+ { - a } - > std:: common_with< T> ;
+ { a + b } - > std:: common_with< T> ;
+ { a - b } - > std:: common_with< T> ;
+ { a * s } - > std:: common_with< T> ;
+ { s * a } - > std:: common_with< T> ;
+ { a / s } - > std:: common_with< T> ;
+ :: mp_units:: magnitude( a) ;
+ } ;
+
template < typename T>
+using scaling-factor-type-t =
+ std:: conditional_t< treat_as_floating_point< T> , long double , std:: intmax_t> ;
+
+template < typename T>
+concept ScalarRepresentation =
+ ( ! is-specialization-of < T, quantity> ( ) ) & & Scalar < T> & &
+ requires ( T a, T b, scaling-factor-type-t < T> f) {
+
+ { a * f } - > std:: common_with< T> ;
+ { f * a } - > std:: common_with< T> ;
+ { a / f } - > std:: common_with< T> ;
+ } ;
+
template < typename T>
+concept ComplexRepresentation =
+ ( ! is-specialization-of < T, quantity> ( ) ) & & Complex < T> & &
+ requires ( T a, T b, scaling-factor-type-t < T> f) {
+
+ { a * T( f) } - > std:: common_with< T> ;
+ { T( f) * a } - > std:: common_with< T> ;
+ { a / T( f) } - > std:: common_with< T> ;
+ } ;
+
template < typename T>
+concept VectorRepresentation =
+ ( ! is-specialization-of < T, quantity> ( ) ) & & Vector < T> ;
+
template < typename T>
+concept Representation = ScalarRepresentation < T> | | ComplexRepresentation < T> | |
+ VectorRepresentation < T> ;
+
template < typename T, quantity_character Ch>
+concept IsOfCharacter = ( Ch = = quantity_character:: scalar & & Scalar < T> ) | |
+ ( Ch = = quantity_character:: complex & & Complex < T> ) | |
+ ( Ch = = quantity_character:: vector & & Vector < T> ) ;
+
+template < typename T, auto V>
+concept RepresentationOf =
+ Representation < T> & & ( ( QuantitySpec < decltype ( V) > & &
+ ( QuantityKindSpec < decltype ( V) > | | IsOfCharacter < T, V. character> ) ) | |
+ ( std:: same_as< quantity_character, decltype ( V) > & & IsOfCharacter < T, V> ) ) ;
+
A type
T models
RepresentationOf < V> if
+
T models
Representation and
+
V is a kind of quantity, orif V is a quantity, then T represents a value of its character, or if V is a quantity character, then T represents a value of V . The interfaces specified in this subclause and subclause
[qty. pt. like]
+are used by
quantity and
quantity_ point
+to specify conversions with other types representing quantities
. [
Note 1 :
[qty. chrono] implements them for
std:: chrono:: duration and
std:: chrono:: time_ point . —
end note ]
template < typename T, template < typename > typename Traits>
+concept qty-like-impl = requires ( const T& qty, const Traits< T> :: rep& num) {
+ { Traits< T> :: to_numerical_value( qty) } - > std:: same_as< typename Traits< T> :: rep> ;
+ { Traits< T> :: from_numerical_value( num) } - > std:: same_as< T> ;
+ requires std:: same_as< decltype ( Traits< T> :: explicit_import) , const bool > ;
+ requires std:: same_as< decltype ( Traits< T> :: explicit_export) , const bool > ;
+ typename std:: bool_constant< Traits< T> :: explicit_import> ;
+ typename std:: bool_constant< Traits< T> :: explicit_export> ;
+} ;
+
+template < typename T>
+concept QuantityLike = ! Quantity < T> & & qty-like-impl < T, quantity_like_traits> & & requires {
+ typename quantity< quantity_like_traits< T> :: reference, typename quantity_like_traits< T> :: rep> ;
+} ;
+
In the following descriptions, let
+
Traits be quantity_ like_ traits or quantity_ point_ like_ traits ,Q be a type for which Traits< Q> is specialized,qty be an lvalue of type const Q , andnum be an lvalue of type const Traits< Q> :: rep. Q models
qty-like-impl < Traits> if and only if:
+
Traits< Q> :: from_ numerical_ value( num) returns a
Q with numerical value
num . If
Traits is
quantity_ point_ like_ traits ,
+both numerical values are offset from
Traits< Q> :: point_ origin . If the following expression is
true , the specified conversion will be explicit
. Traits< Q> :: explicit_ import for the conversion from
Q to this library's type
. Traits< Q> :: explicit_ export for the conversion from this library's type to
Q . namespace mp_units {
+
+template < typename T>
+concept Quantity = ( is-derived-from-specialization-of < T, quantity> ( ) ) ;
+
+template < typename Q, auto QS>
+concept QuantityOf =
+ Quantity < Q> & & QuantitySpecOf < decltype ( auto ( Q:: quantity_spec) ) , QS> ;
+
+template < Unit UFrom, Unit UTo>
+consteval bool integral-conversion-factor ( UFrom from, UTo to)
+{
+ return is-integral ( get-canonical-unit ( from) . mag / get-canonical-unit ( to) . mag) ;
+}
+
+template < typename T>
+concept IsFloatingPoint = treat_as_floating_point< T> ;
+
+template < typename FromRep, typename ToRep, auto FromUnit = one, auto ToUnit = one>
+concept ValuePreservingTo =
+ Representation < std:: remove_cvref_t< FromRep> > & & Representation < ToRep> & &
+ Unit < decltype ( FromUnit) > & & Unit < decltype ( ToUnit) > & & std:: assignable_from< ToRep& , FromRep> & &
+ ( IsFloatingPoint < ToRep> | | ( ! IsFloatingPoint < std:: remove_cvref_t< FromRep> > & &
+ ( integral-conversion-factor ( FromUnit, ToUnit) ) ) ) ;
+
+template < typename QFrom, typename QTo>
+concept QuantityConvertibleTo =
+ Quantity < QFrom> & & Quantity < QTo> & &
+ QuantitySpecConvertibleTo < QFrom:: quantity_spec, QTo:: quantity_spec> & &
+ UnitConvertibleTo < QFrom:: unit, QTo:: unit> & &
+ ValuePreservingTo < typename QFrom:: rep, typename QTo:: rep, QFrom:: unit, QTo:: unit> & &
+ requires ( QFrom q) { sudo-cast < QTo> ( q) ; } ;
+
+template < auto QS, typename Func, typename T, typename U>
+concept InvokeResultOf =
+ QuantitySpec < decltype ( QS) > & & std:: regular_invocable< Func, T, U> & &
+ RepresentationOf < std:: invoke_result_t< Func, T, U> , QS> ;
+
+template < typename Func, typename Q1, typename Q2,
+ auto QS = std:: invoke_result_t< Func, decltype ( auto ( Q1:: quantity_spec) ) ,
+ decltype ( auto ( Q2:: quantity_spec) ) > { } >
+concept InvocableQuantities =
+ QuantitySpec < decltype ( QS) > & & Quantity < Q1> & & Quantity < Q2> & &
+ InvokeResultOf < QS, Func, typename Q1:: rep, typename Q2:: rep> ;
+
+template < auto R1, auto R2>
+concept HaveCommonReference = requires { get_common_reference( R1, R2) ; } ;
+
+template < typename Func, Quantity Q1, Quantity Q2>
+using common-quantity-for =
+ quantity< get_common_reference( Q1:: reference, Q2:: reference) ,
+ std:: invoke_result_t< Func, typename Q1:: rep, typename Q2:: rep> > ;
+
+template < typename Func, typename Q1, typename Q2>
+concept CommonlyInvocableQuantities =
+ Quantity < Q1> & & Quantity < Q2> & & HaveCommonReference < Q1:: reference, Q2:: reference> & &
+ std:: convertible_to< Q1, common-quantity-for < Func, Q1, Q2> > & &
+ std:: convertible_to< Q2, common-quantity-for < Func, Q1, Q2> > & &
+ InvocableQuantities < Func, Q1, Q2,
+ get_common_quantity_spec( Q1:: quantity_spec, Q2:: quantity_spec) > ;
+
+template < auto R1, auto R2, typename Rep1, typename Rep2>
+concept SameValueAs =
+ ( equivalent( get_unit( R1) , get_unit( R2) ) ) & & std:: convertible_to< Rep1, Rep2> ;
+
+template < typename T>
+using quantity-like-type =
+ quantity< quantity_like_traits< T> :: reference, typename quantity_like_traits< T> :: rep> ;
+
+template < typename T, typename U, typename TT = std:: remove_reference_t< T> >
+concept Mutable = ( ! std:: is_const_v< TT> ) & & std:: derived_from< TT, U> ;
+
+template < Reference auto R, RepresentationOf < get_quantity_spec( R) > Rep = double >
+class quantity {
+public :
+ Rep numerical-value ;
+
+
+ static constexpr Reference auto reference = R;
+ static constexpr QuantitySpec auto quantity_spec = get_quantity_spec( reference) ;
+ static constexpr Dimension auto dimension = quantity_spec. dimension;
+ static constexpr Unit auto unit = get_unit( reference) ;
+ using rep = Rep;
+
+
+ static constexpr quantity zero( ) noexcept
+ requires see below ;
+ static constexpr quantity one( ) noexcept
+ requires see below ;
+ static constexpr quantity min( ) noexcept
+ requires see below ;
+ static constexpr quantity max( ) noexcept
+ requires see below ;
+
+
+
+ quantity( ) = default ;
+ quantity( const quantity& ) = default ;
+ quantity( quantity& & ) = default ;
+ ~ quantity( ) = default ;
+
+ template < typename FwdValue, Reference R2>
+ requires SameValueAs < R2{ } , R, std:: remove_cvref_t< FwdValue> , Rep>
+ constexpr quantity( FwdValue& & v, R2) ;
+
+ template < typename FwdValue, Reference R2, typename Value = std:: remove_cvref_t< FwdValue> >
+ requires ( ! SameValueAs < R2{ } , R, Value, Rep> ) & &
+ QuantityConvertibleTo < quantity< R2{ } , Value> , quantity>
+ constexpr quantity( FwdValue& & v, R2) ;
+
+ template < ValuePreservingTo < Rep> FwdValue>
+ requires ( unit = = :: mp_units:: one)
+ constexpr quantity( FwdValue& & v) ;
+
+ template < QuantityConvertibleTo < quantity> Q>
+ constexpr explicit ( see below ) quantity( const Q& q) ;
+
+ template < QuantityLike Q>
+ requires QuantityConvertibleTo < quantity-like-type < Q> , quantity>
+ constexpr explicit ( see below ) quantity( const Q& q) ;
+
+ quantity& operator = ( const quantity& ) = default ;
+ quantity& operator = ( quantity& & ) = default ;
+
+ template < ValuePreservingTo < Rep> FwdValue>
+ requires ( unit = = :: mp_units:: one)
+ constexpr quantity& operator = ( FwdValue& & v) ;
+
+
+
+ template < UnitCompatibleWith < unit, quantity_spec> ToU>
+ requires QuantityConvertibleTo < quantity, quantity< make-reference ( quantity_spec, ToU{ } ) , Rep> >
+ constexpr QuantityOf < quantity_spec> auto in( ToU) const ;
+
+ template < RepresentationOf < quantity_spec> ToRep>
+ requires QuantityConvertibleTo < quantity, quantity< reference, ToRep> >
+ constexpr QuantityOf < quantity_spec> auto in( ) const ;
+
+ template < RepresentationOf < quantity_spec> ToRep,
+ UnitCompatibleWith < unit, quantity_spec> ToU>
+ requires QuantityConvertibleTo < quantity,
+ quantity< make-reference ( quantity_spec, ToU{ } ) , ToRep> >
+ constexpr QuantityOf < quantity_spec> auto in( ToU) const ;
+
+ template < UnitCompatibleWith < unit, quantity_spec> ToU>
+ requires requires ( const quantity q) { value_cast< ToU{ } > ( q) ; }
+ constexpr QuantityOf < quantity_spec> auto force_in( ToU) const ;
+
+ template < RepresentationOf < quantity_spec> ToRep>
+ requires requires ( const quantity q) { value_cast< ToRep> ( q) ; }
+ constexpr QuantityOf < quantity_spec> auto force_in( ) const ;
+
+ template < RepresentationOf < quantity_spec> ToRep,
+ UnitCompatibleWith < unit, quantity_spec> ToU>
+ requires requires ( const quantity q) { value_cast< ToU{ } , ToRep> ( q) ; }
+ constexpr QuantityOf < quantity_spec> auto force_in( ToU) const ;
+
+
+
+ template < Unit U>
+ requires ( equivalent( U{ } , unit) )
+ constexpr rep& numerical_value_ref_in( U) & noexcept ;
+ template < Unit U>
+ requires ( equivalent( U{ } , unit) )
+ constexpr const rep& numerical_value_ref_in( U) const & noexcept ;
+ template < Unit U>
+ requires ( equivalent( U{ } , unit) )
+ void numerical_value_ref_in( U) const & & = delete ;
+
+ template < UnitCompatibleWith < unit, quantity_spec> U>
+ requires QuantityConvertibleTo < quantity, quantity< make-reference ( quantity_spec, U{ } ) , Rep> >
+ constexpr rep numerical_value_in( U) const noexcept ;
+
+ template < UnitCompatibleWith < unit, quantity_spec> U>
+ requires requires ( const quantity q) { value_cast< U{ } > ( q) ; }
+ constexpr rep force_numerical_value_in( U) const noexcept ;
+
+
+
+ template < typename V_, std:: constructible_from< Rep> Value = std:: remove_cvref_t< V_> >
+ requires ( unit = = :: mp_units:: one)
+ explicit operator V_( ) const & noexcept ;
+
+ template < typename Q_, QuantityLike Q = std:: remove_cvref_t< Q_> >
+ requires QuantityConvertibleTo < quantity, quantity-like-type < Q> >
+ constexpr explicit ( see below ) operator Q_( ) const noexcept ( see below ) ;
+
+
+
+ constexpr QuantityOf < quantity_spec> auto operator + ( ) const
+ requires see below ;
+ constexpr QuantityOf < quantity_spec> auto operator - ( ) const
+ requires see below ;
+
+ template < Mutable < quantity> Q>
+ friend constexpr decltype ( auto ) operator + + ( Q& & q)
+ requires see below ;
+ template < Mutable < quantity> Q>
+ friend constexpr decltype ( auto ) operator - - ( Q& & q)
+ requires see below ;
+
+ constexpr QuantityOf < quantity_spec> auto operator + + ( int )
+ requires see below ;
+ constexpr QuantityOf < quantity_spec> auto operator - - ( int )
+ requires see below ;
+
+
+
+ template < Mutable < quantity> Q, auto R2, typename Rep2>
+ requires see below
+ friend constexpr decltype ( auto ) operator + = ( Q& & lhs, const quantity< R2, Rep2> & rhs) ;
+ template < Mutable < quantity> Q, auto R2, typename Rep2>
+ requires see below
+ friend constexpr decltype ( auto ) operator - = ( Q& & lhs, const quantity< R2, Rep2> & rhs) ;
+ template < Mutable < quantity> Q, auto R2, typename Rep2>
+ requires see below
+ friend constexpr decltype ( auto ) operator % = ( Q& & lhs, const quantity< R2, Rep2> & rhs) ;
+
+ template < Mutable < quantity> Q, ValuePreservingTo < Rep> Value>
+ requires see below
+ friend constexpr decltype ( auto ) operator * = ( Q& & lhs, const Value& rhs) ;
+ template < Mutable < quantity> Q, ValuePreservingTo < Rep> Value>
+ requires see below
+ friend constexpr decltype ( auto ) operator / = ( Q& & lhs, const Value& rhs) ;
+
+ template < Mutable < quantity> Q, QuantityOf < dimensionless> Q2>
+ requires see below
+ friend constexpr decltype ( auto ) operator * = ( Q& & lhs, const Q2& rhs) ;
+ template < Mutable < quantity> Q, QuantityOf < dimensionless> Q2>
+ requires see below
+ friend constexpr decltype ( auto ) operator / = ( Q& & lhs, const Q2& rhs) ;
+
+
+
+ template < std:: derived_from< quantity> Q, auto R2, typename Rep2>
+ requires CommonlyInvocableQuantities < std:: plus< > , quantity, quantity< R2, Rep2> >
+ friend constexpr Quantity auto operator + ( const Q& lhs, const quantity< R2, Rep2> & rhs) ;
+ template < std:: derived_from< quantity> Q, auto R2, typename Rep2>
+ requires CommonlyInvocableQuantities < std:: minus< > , quantity, quantity< R2, Rep2> >
+ friend constexpr Quantity auto operator - ( const Q& lhs, const quantity< R2, Rep2> & rhs) ;
+ template < std:: derived_from< quantity> Q, auto R2, typename Rep2>
+ requires ( ! treat_as_floating_point< Rep> ) & & ( ! treat_as_floating_point< Rep2> ) & &
+ CommonlyInvocableQuantities < std:: modulus< > , quantity, quantity< R2, Rep2> >
+ friend constexpr Quantity auto operator % ( const Q& lhs, const quantity< R2, Rep2> & rhs) ;
+
+ template < std:: derived_from< quantity> Q, Representation Value>
+ requires ( Q:: unit = = :: mp_units:: one) & &
+ InvokeResultOf < quantity_spec, std:: plus< > , Rep, const Value& >
+ friend constexpr Quantity auto operator + ( const Q& lhs, const Value& rhs) ;
+ template < std:: derived_from< quantity> Q, Representation Value>
+ requires ( Q:: unit = = :: mp_units:: one) & &
+ InvokeResultOf < quantity_spec, std:: minus< > , Rep, const Value& >
+ friend constexpr Quantity auto operator - ( const Q& lhs, const Value& rhs) ;
+ template < std:: derived_from< quantity> Q, Representation Value>
+ requires ( Q:: unit = = :: mp_units:: one) & &
+ InvokeResultOf < quantity_spec, std:: modulus< > , Rep, const Value& >
+ friend constexpr Quantity auto operator % ( const Q& lhs, const Value& rhs) ;
+
+ template < std:: derived_from< quantity> Q, Representation Value>
+ requires ( Q:: unit = = :: mp_units:: one) & &
+ InvokeResultOf < quantity_spec, std:: plus< > , Rep, const Value& >
+ friend constexpr Quantity auto operator + ( const Value& lhs, const Q& rhs) ;
+ template < std:: derived_from< quantity> Q, Representation Value>
+ requires ( Q:: unit = = :: mp_units:: one) & &
+ InvokeResultOf < quantity_spec, std:: minus< > , Rep, const Value& >
+ friend constexpr Quantity auto operator - ( const Value& lhs, const Q& rhs) ;
+ template < std:: derived_from< quantity> Q, Representation Value>
+ requires ( Q:: unit = = :: mp_units:: one) & &
+ InvokeResultOf < quantity_spec, std:: modulus< > , Rep, const Value& >
+ friend constexpr Quantity auto operator % ( const Value& lhs, const Q& rhs) ;
+
+ template < std:: derived_from< quantity> Q, auto R2, typename Rep2>
+ requires InvocableQuantities < std:: multiplies< > , quantity, quantity< R2, Rep2> >
+ friend constexpr Quantity auto operator * ( const Q& lhs, const quantity< R2, Rep2> & rhs) ;
+ template < std:: derived_from< quantity> Q, auto R2, typename Rep2>
+ requires InvocableQuantities < std:: divides< > , quantity, quantity< R2, Rep2> >
+ friend constexpr Quantity auto operator / ( const Q& lhs, const quantity< R2, Rep2> & rhs) ;
+
+ template < std:: derived_from< quantity> Q, typename Value>
+ requires ( ! Quantity < Value> ) & & ( ! Reference < Value> ) & &
+ InvokeResultOf < quantity_spec, std:: multiplies< > , Rep, const Value& >
+ friend constexpr QuantityOf < quantity_spec> auto operator * ( const Q& lhs, const Value& rhs) ;
+ template < std:: derived_from< quantity> Q, typename Value>
+ requires ( ! Quantity < Value> ) & & ( ! Reference < Value> ) & &
+ InvokeResultOf < quantity_spec, std:: divides< > , Rep, const Value& >
+ friend constexpr QuantityOf < quantity_spec> auto operator / ( const Q& lhs, const Value& rhs) ;
+
+ template < typename Value, std:: derived_from< quantity> Q>
+ requires ( ! Quantity < Value> ) & & ( ! Reference < Value> ) & &
+ InvokeResultOf < quantity_spec, std:: multiplies< > , const Value& , Rep>
+ friend constexpr QuantityOf < quantity_spec> auto operator * ( const Value& lhs, const Q& rhs) ;
+ template < typename Value, std:: derived_from< quantity> Q>
+ requires ( ! Quantity < Value> ) & & ( ! Reference < Value> ) & &
+ InvokeResultOf < quantity_spec, std:: divides< > , const Value& , Rep>
+ friend constexpr Quantity auto operator / ( const Value& , const Q& ) ;
+
+
+
+ template < std:: derived_from< quantity> Q, auto R2, typename Rep2>
+ requires see below
+ friend constexpr bool operator = = ( const Q& lhs, const quantity< R2, Rep2> & rhs) ;
+ template < std:: derived_from< quantity> Q, auto R2, typename Rep2>
+ requires see below
+ friend constexpr auto operator < = > ( const Q& lhs, const quantity< R2, Rep2> & rhs) ;
+
+ template < std:: derived_from< quantity> Q, Representation Value>
+ requires see below
+ friend constexpr bool operator = = ( const Q& lhs, const Value& rhs) ;
+ template < std:: derived_from< quantity> Q, Representation Value>
+ requires see below
+ friend constexpr auto operator < = > ( const Q& lhs, const Value& rhs) ;
+
+
+ friend constexpr bool is_eq_zero( const quantity& q) requires see below ;
+ friend constexpr bool is_neq_zero( const quantity& q) requires see below ;
+ friend constexpr bool is_lt_zero( const quantity& q) requires see below ;
+ friend constexpr bool is_gt_zero( const quantity& q) requires see below ;
+ friend constexpr bool is_lteq_zero( const quantity& q) requires see below ;
+ friend constexpr bool is_gteq_zero( const quantity& q) requires see below ;
+} ;
+
+template < Representation Value, Reference R>
+quantity( Value, R) - > quantity< R{ } , Value> ;
+
+template < Representation Value>
+quantity( Value) - > quantity< one, Value> ;
+
+template < QuantityLike Q>
+explicit ( quantity_like_traits< Q> :: explicit_import) quantity( Q)
+ - > quantity< quantity_like_traits< Q> :: reference, typename quantity_like_traits< Q> :: rep> ;
+
+}
+static constexpr quantity zero( ) noexcept
+ requires see below ;
+static constexpr quantity one( ) noexcept
+ requires see below ;
+static constexpr quantity min( ) noexcept
+ requires see below ;
+static constexpr quantity max( ) noexcept
+ requires see below ;
+
Let
F be one of
zero ,
one ,
min , and
max . Returns :
{ representation_ values< rep> :: F ( ) , R} . Remarks : The expression in the requires-clause is equivalent to:
+requires { representation_values< rep> :: F ( ) ; }
+
template < typename FwdValue, Reference R2>
+ requires SameValueAs < R2{ } , R, std:: remove_cvref_t< FwdValue> , Rep>
+constexpr quantity( FwdValue& & v, R2) ;
+
+template < ValuePreservingTo < Rep> FwdValue>
+ requires ( unit = = :: mp_units:: one)
+constexpr quantity( FwdValue& & v) ;
+
Effects : Initializes
numerical-value with
std:: forward< FwdValue> ( v) . template < typename FwdValue, Reference R2, typename Value = std:: remove_cvref_t< FwdValue> >
+ requires ( ! SameValueAs < R2{ } , R, Value, Rep> ) & &
+ QuantityConvertibleTo < quantity< R2{ } , Value> , quantity>
+constexpr quantity( FwdValue& & v, R2) ;
+
Effects : Equivalent to
+
quantity( quantity< R2{ } , Value> { std:: forward< FwdValue> ( v) , R2{ } } ) . template < QuantityConvertibleTo < quantity> Q>
+constexpr explicit ( ! std:: convertible_to< typename Q:: rep, Rep> ) quantity( const Q& q) ;
+
template < QuantityLike Q>
+ requires QuantityConvertibleTo < quantity-like-type < Q> , quantity>
+constexpr explicit ( see below ) quantity( const Q& q) ;
+
Effects : Equivalent to:
+quantity( :: mp_units:: quantity{ quantity_like_traits< Q> :: to_numerical_value( q) ,
+ quantity_like_traits< Q> :: reference} )
+
Remarks : The expression inside explicit is equivalent to:
+quantity_like_traits< Q> :: explicit_import | |
+ ! std:: convertible_to< typename quantity_like_traits< Q> :: rep, Rep>
+
template < ValuePreservingTo < Rep> FwdValue>
+ requires ( unit = = :: mp_units:: one)
+constexpr quantity& operator = ( FwdValue& & v) ;
+
Effects : Equivalent to
numerical-value = std:: forward< FwdValue> ( v) . template < UnitCompatibleWith < unit, quantity_spec> ToU>
+ requires QuantityConvertibleTo < quantity, quantity< make-reference ( quantity_spec, ToU{ } ) , Rep> >
+constexpr QuantityOf < quantity_spec> auto in( ToU) const ;
+
Effects : Equivalent to:
+return quantity< make-reference ( quantity_ spec, ToU{ } ) , Rep> { * this } ;
template < RepresentationOf < quantity_spec> ToRep>
+ requires QuantityConvertibleTo < quantity, quantity< reference, ToRep> >
+constexpr QuantityOf < quantity_spec> auto in( ) const ;
+
Effects : Equivalent to:
+return quantity< reference, ToRep> { * this } ;
template < RepresentationOf < quantity_spec> ToRep,
+ UnitCompatibleWith < unit, quantity_spec> ToU>
+ requires QuantityConvertibleTo < quantity,
+ quantity< make-reference ( quantity_spec, ToU{ } ) , ToRep> >
+constexpr QuantityOf < quantity_spec> auto in( ToU) const ;
+
Effects : Equivalent to:
+return quantity< make-reference ( quantity_spec, ToU{ } ) , ToRep> { * this } ;
+
template < UnitCompatibleWith < unit, quantity_spec> ToU>
+ requires requires ( const quantity q) { value_cast< ToU{ } > ( q) ; }
+constexpr QuantityOf < quantity_spec> auto force_in( ToU) const ;
+
Effects : Equivalent to:
+return value_ cast< ToU{ } > ( * this ) ;
template < RepresentationOf < quantity_spec> ToRep>
+ requires requires ( const quantity q) { value_cast< ToRep> ( q) ; }
+constexpr QuantityOf < quantity_spec> auto force_in( ) const ;
+
Effects : Equivalent to:
+return value_ cast< ToRep> ( * this ) ;
template < RepresentationOf < quantity_spec> ToRep,
+ UnitCompatibleWith < unit, quantity_spec> ToU>
+ requires requires ( const quantity q) { value_cast< ToU{ } , ToRep> ( q) ; }
+constexpr QuantityOf < quantity_spec> auto force_in( ToU) const ;
+
Effects : Equivalent to:
+return value_ cast< ToU{ } , ToRep> ( * this ) ;
template < Unit U>
+ requires ( equivalent( U{ } , unit) )
+constexpr rep& numerical_value_ref_in( U) & noexcept ;
+template < Unit U>
+ requires ( equivalent( U{ } , unit) )
+constexpr const rep& numerical_value_ref_in( U) const & noexcept ;
+
Returns :
numerical-value . template < UnitCompatibleWith < unit, quantity_spec> U>
+ requires QuantityConvertibleTo < quantity, quantity< make-reference ( quantity_spec, U{ } ) , Rep> >
+constexpr rep numerical_value_in( U) const noexcept ;
+
Effects : Equivalent to:
+return ( * this ) . in( U{ } ) . numerical-value ;
template < UnitCompatibleWith < unit, quantity_spec> U>
+ requires requires ( const quantity q) { value_cast< U{ } > ( q) ; }
+constexpr rep force_numerical_value_in( U) const noexcept ;
+
Effects : Equivalent to:
+return ( * this ) . force_ in( U{ } ) . numerical-value ;
template < typename V_, std:: constructible_from< Rep> Value = std:: remove_cvref_t< V_> >
+ requires ( unit = = :: mp_units:: one)
+explicit operator V_( ) const & noexcept ;
+
Returns :
numerical-value . template < typename Q_, QuantityLike Q = std:: remove_cvref_t< Q_> >
+ requires QuantityConvertibleTo < quantity, quantity-like-type < Q> >
+constexpr explicit ( see below ) operator Q_( ) const noexcept ( see below ) ;
+
Effects : Equivalent to:
+return quantity_like_traits< Q> :: from_numerical_value(
+ numerical_value_in( get_unit( quantity_like_traits< Q> :: reference) ) ) ;
+
Remarks : The expression inside explicit is equivalent to:
+quantity_like_traits< Q> :: explicit_export | |
+ ! std:: convertible_to< Rep, typename quantity_like_traits< Q> :: rep>
+
+The exception specification is equivalent to:
+noexcept ( quantity_like_traits< Q> :: from_numerical_value( numerical-value ) ) & &
+ std:: is_nothrow_copy_constructible_v< rep>
+
In the following descriptions,
+let
@ be the
operator . constexpr QuantityOf < quantity_spec> auto operator + ( ) const
+ requires see below ;
+constexpr QuantityOf < quantity_spec> auto operator - ( ) const
+ requires see below ;
+
Effects : Equivalent to:
+return :: mp_ units:: quantity{ @numerical-value , reference} ;
Remarks : The expression in the requires-clause is equivalent to:
+requires ( const rep v) {
+ { @v } - > std:: common_with< rep> ;
+}
+
template < Mutable < quantity> Q>
+friend constexpr decltype ( auto ) operator + + ( Q& & q)
+ requires see below ;
+template < Mutable < quantity> Q>
+friend constexpr decltype ( auto ) operator - - ( Q& & q)
+ requires see below ;
+
Effects : Equivalent to
+
@q. numerical-value . Returns :
std:: forward< Q> ( q) . Remarks : The expression in the requires-clause is equivalent to:
+requires ( rep& v) {
+ { @v } - > std:: same_as< rep& > ;
+}
+
constexpr QuantityOf < quantity_spec> auto operator + + ( int )
+ requires see below ;
+constexpr QuantityOf < quantity_spec> auto operator - - ( int )
+ requires see below ;
+
Effects : Equivalent to:
+return :: mp_ units:: quantity{ numerical-value @, reference} ;
Remarks : The expression in the requires-clause is equivalent to:
+requires ( rep& v) {
+ { v@ } - > std:: common_with< rep> ;
+}
+
In the following descriptions,
+let
@ be the
operator . template < Mutable < quantity> Q, auto R2, typename Rep2>
+ requires see below
+friend constexpr decltype ( auto ) operator + = ( Q& & lhs, const quantity< R2, Rep2> & rhs) ;
+template < Mutable < quantity> Q, auto R2, typename Rep2>
+ requires see below
+friend constexpr decltype ( auto ) operator - = ( Q& & lhs, const quantity< R2, Rep2> & rhs) ;
+template < Mutable < quantity> Q, auto R2, typename Rep2>
+ requires see below
+friend constexpr decltype ( auto ) operator % = ( Q& & lhs, const quantity< R2, Rep2> & rhs) ;
+
Preconditions : If
@ is
% = , then
is_ neq_ zero( rhs) is
true . Effects : Equivalent to
+
lhs. numerical-value @ rhs. in( lhs. unit) . numerical-value . Returns :
std:: forward< Q> ( lhs) . Remarks : Let
C be
+
( ! treat_ as_ floating_ point< rep> ) if @ is % = , andtrue otherwise.
+The expression in the
requires-clause is equivalent to:
+
QuantityConvertibleTo < quantity< R2, Rep2> , quantity> & & C & &
+requires ( rep& a, const Rep2 b) {
+ { a @ b } - > std:: same_as< rep& > ;
+}
+Recommended practice : If
equivalent( unit, get_ unit( rhs. reference) ) is
true ,
+then the expression
rhs. in( lhs. unit) is replaced with
rhs . template < Mutable < quantity> Q, ValuePreservingTo < Rep> Value>
+ requires see below
+friend constexpr decltype ( auto ) operator * = ( Q& & lhs, const Value& rhs) ;
+template < Mutable < quantity> Q, ValuePreservingTo < Rep> Value>
+ requires see below
+friend constexpr decltype ( auto ) operator / = ( Q& & lhs, const Value& rhs) ;
+
Preconditions : If
@ is
/ = , then
rhs ! = representation_ values< Value> :: zero( ) is
true . Effects : Equivalent to
+
lhs. numerical-value @ rhs . Returns :
std:: forward< Q> ( lhs) . Remarks : The expression in the
requires-clause is equivalent to:
+
( ! Quantity < Value> ) & & requires ( rep& a, const Value b) {
+ { a @ b } - > std:: same_as< rep& > ;
+}
+template < Mutable < quantity> Q, QuantityOf < dimensionless> Q2>
+ requires see below
+friend constexpr decltype ( auto ) operator * = ( Q& & lhs, const Q2& rhs) ;
+template < Mutable < quantity> Q, QuantityOf < dimensionless> Q2>
+ requires see below
+friend constexpr decltype ( auto ) operator / = ( Q& & lhs, const Q2& rhs) ;
+
Effects : Equivalent to:
+return std:: forward< Q> ( lhs) @ rhs. numerical-value ;
Remarks : The expression in the
requires-clause is equivalent to:
+
( Q2:: unit = = :: mp_units:: one) & & ValuePreservingTo < typename Q2:: rep, Rep> & &
+requires ( rep& a, const Q2:: rep b) {
+ { a @ b } - > std:: same_as< rep& > ;
+}
+In the following descriptions,
+let
@ be the
operator . template < std:: derived_from< quantity> Q, auto R2, typename Rep2>
+ requires CommonlyInvocableQuantities < std:: plus< > , quantity, quantity< R2, Rep2> >
+friend constexpr Quantity auto operator + ( const Q& lhs, const quantity< R2, Rep2> & rhs) ;
+template < std:: derived_from< quantity> Q, auto R2, typename Rep2>
+ requires CommonlyInvocableQuantities < std:: minus< > , quantity, quantity< R2, Rep2> >
+friend constexpr Quantity auto operator - ( const Q& lhs, const quantity< R2, Rep2> & rhs) ;
+template < std:: derived_from< quantity> Q, auto R2, typename Rep2>
+ requires ( ! treat_as_floating_point< Rep> ) & & ( ! treat_as_floating_point< Rep2> ) & &
+ CommonlyInvocableQuantities < std:: modulus< > , quantity, quantity< R2, Rep2> >
+friend constexpr Quantity auto operator % ( const Q& lhs, const quantity< R2, Rep2> & rhs) ;
+
Let
F be the first argument to
CommonlyInvocableQuantities . Preconditions : If
@ is
% , then
is_ neq_ zero( rhs) is
true . Effects : Equivalent to:
+using ret = common-quantity-for < F , quantity, quantity< R2, Rep2> > ;
+const ret ret_lhs( lhs) ;
+const ret ret_rhs( rhs) ;
+return :: mp_units:: quantity{
+ ret_lhs. numerical_value_ref_in( ret:: unit) @ ret_rhs. numerical_value_ref_in( ret:: unit) ,
+ ret:: reference} ;
+
template < std:: derived_from< quantity> Q, Representation Value>
+ requires ( Q:: unit = = :: mp_units:: one) & &
+ InvokeResultOf < quantity_spec, std:: plus< > , Rep, const Value& >
+friend constexpr Quantity auto operator + ( const Q& lhs, const Value& rhs) ;
+template < std:: derived_from< quantity> Q, Representation Value>
+ requires ( Q:: unit = = :: mp_units:: one) & &
+ InvokeResultOf < quantity_spec, std:: minus< > , Rep, const Value& >
+friend constexpr Quantity auto operator - ( const Q& lhs, const Value& rhs) ;
+template < std:: derived_from< quantity> Q, Representation Value>
+ requires ( Q:: unit = = :: mp_units:: one) & &
+ InvokeResultOf < quantity_spec, std:: modulus< > , Rep, const Value& >
+friend constexpr Quantity auto operator % ( const Q& lhs, const Value& rhs) ;
+
Effects : Equivalent to:
+return lhs @ :: mp_ units:: quantity{ rhs} ;
template < std:: derived_from< quantity> Q, Representation Value>
+ requires ( Q:: unit = = :: mp_units:: one) & &
+ InvokeResultOf < quantity_spec, std:: plus< > , Rep, const Value& >
+friend constexpr Quantity auto operator + ( const Value& lhs, const Q& rhs) ;
+template < std:: derived_from< quantity> Q, Representation Value>
+ requires ( Q:: unit = = :: mp_units:: one) & &
+ InvokeResultOf < quantity_spec, std:: minus< > , Rep, const Value& >
+friend constexpr Quantity auto operator - ( const Value& lhs, const Q& rhs) ;
+template < std:: derived_from< quantity> Q, Representation Value>
+ requires ( Q:: unit = = :: mp_units:: one) & &
+ InvokeResultOf < quantity_spec, std:: modulus< > , Rep, const Value& >
+friend constexpr Quantity auto operator % ( const Value& lhs, const Q& rhs) ;
+
Effects : Equivalent to:
+return :: mp_ units:: quantity{ lhs} @ rhs;
template < std:: derived_from< quantity> Q, auto R2, typename Rep2>
+ requires InvocableQuantities < std:: multiplies< > , quantity, quantity< R2, Rep2> >
+friend constexpr Quantity auto operator * ( const Q& lhs, const quantity< R2, Rep2> & rhs) ;
+template < std:: derived_from< quantity> Q, auto R2, typename Rep2>
+ requires InvocableQuantities < std:: divides< > , quantity, quantity< R2, Rep2> >
+friend constexpr Quantity auto operator / ( const Q& lhs, const quantity< R2, Rep2> & rhs) ;
+
Preconditions : If
@ is
/ , then
is_ neq_ zero( rhs) is
true . Effects : Equivalent to:
+return :: mp_units:: quantity{
+ lhs. numerical_value_ref_in( unit) @ rhs. numerical_value_ref_in( rhs. unit) , R @ R2} ;
+
template < std:: derived_from< quantity> Q, typename Value>
+ requires ( ! Quantity < Value> ) & & ( ! Reference < Value> ) & &
+ InvokeResultOf < quantity_spec, std:: multiplies< > , Rep, const Value& >
+friend constexpr QuantityOf < quantity_spec> auto operator * ( const Q& lhs, const Value& rhs) ;
+template < std:: derived_from< quantity> Q, typename Value>
+ requires ( ! Quantity < Value> ) & & ( ! Reference < Value> ) & &
+ InvokeResultOf < quantity_spec, std:: divides< > , Rep, const Value& >
+friend constexpr QuantityOf < quantity_spec> auto operator / ( const Q& lhs, const Value& rhs) ;
+
Preconditions : If
@ is
/ , then
rhs ! = representation_ values< Value> :: zero( ) is
true . Effects : Equivalent to:
+return :: mp_units:: quantity{ lhs. numerical_value_ref_in( unit) @ rhs, R} ;
+
template < typename Value, std:: derived_from< quantity> Q>
+ requires ( ! Quantity < Value> ) & & ( ! Reference < Value> ) & &
+ InvokeResultOf < quantity_spec, std:: multiplies< > , const Value& , Rep>
+friend constexpr QuantityOf < quantity_spec> auto operator * ( const Value& lhs, const Q& rhs) ;
+template < typename Value, std:: derived_from< quantity> Q>
+ requires ( ! Quantity < Value> ) & & ( ! Reference < Value> ) & &
+ InvokeResultOf < quantity_spec, std:: divides< > , const Value& , Rep>
+friend constexpr Quantity auto operator / ( const Value& lhs, const Q& rhs) ;
+
Preconditions : If
@ is
/ , then
is_ neq_ zero( rhs) is
true . Effects : Equivalent to:
+return :: mp_units:: quantity{ lhs @ rhs. numerical_value_ref_in( unit) , :: mp_units:: one @ R} ;
+
In the following descriptions,
+let
@ be the
operator . template < std:: derived_from< quantity> Q, auto R2, typename Rep2>
+ requires see below
+friend constexpr bool operator = = ( const Q& lhs, const quantity< R2, Rep2> & rhs) ;
+template < std:: derived_from< quantity> Q, auto R2, typename Rep2>
+ requires see below
+friend constexpr auto operator < = > ( const Q& lhs, const quantity< R2, Rep2> & rhs) ;
+
Let
C be
+
std:: equality_ comparable if
@ is
= = , and
+
std:: three_ way_ comparable if
@ is
< = > . Effects : Equivalent to:
+using ct = std:: common_type_t< quantity, quantity< R2, Rep2> > ;
+const ct ct_lhs( lhs) ;
+const ct ct_rhs( rhs) ;
+return ct_lhs. numerical_value_ref_in( ct:: unit) @ ct_rhs. numerical_value_ref_in( ct:: unit) ;
+
Remarks : The expression in the requires-clause is equivalent to:
+requires {
+ typename std:: common_type_t< quantity, quantity< R2, Rep2> > ;
+} & & C < typename std:: common_type_t< quantity, quantity< R2, Rep2> > :: rep>
+
template < std:: derived_from< quantity> Q, Representation Value>
+ requires see below
+friend constexpr bool operator = = ( const Q& lhs, const Value& rhs) ;
+template < std:: derived_from< quantity> Q, Representation Value>
+ requires see below
+friend constexpr auto operator < = > ( const Q& lhs, const Value& rhs) ;
+
Let
C be
+
std:: equality_ comparable_ with if
@ is
= = , and
+
std:: three_ way_ comparable_ with if
@ is
< = > . Returns :
lhs. numerical_ value_ ref_ in( unit) @ rhs . Remarks : The expression in the requires-clause is equivalent to:
+( Q:: unit = = :: mp_units:: one) & & C < Rep, Value>
+
friend constexpr bool is_eq_zero( const quantity& q) requires see below ;
+friend constexpr bool is_neq_zero( const quantity& q) requires see below ;
+friend constexpr bool is_lt_zero( const quantity& q) requires see below ;
+friend constexpr bool is_gt_zero( const quantity& q) requires see below ;
+friend constexpr bool is_lteq_zero( const quantity& q) requires see below ;
+friend constexpr bool is_gteq_zero( const quantity& q) requires see below ;
+
Let
is_F _ zero be the function name
. Returns :
If
F is
eq , returns
q = = zero( ) . Otherwise, if
F is
neq , returns
q ! = zero( ) . Remarks : Let
C be
+
std:: equality_ comparable_ with if
F is
eq or
neq , and
+
std:: three_ way_ comparable_ with otherwise
. The expression in the requires-clause is equivalent to:
+requires {
+ { T:: zero( ) } - > C < quantity> ;
+}
+
namespace mp_units {
+
+template < Reference R>
+struct delta_ {
+ template < typename FwdRep,
+ RepresentationOf < get_quantity_spec( R{ } ) > Rep = std:: remove_cvref_t< FwdRep> >
+ constexpr quantity< R{ } , Rep> operator ( ) ( FwdRep& & lhs) const ;
+} ;
+
+}
+template < typename FwdRep,
+ RepresentationOf < get_quantity_spec( R{ } ) > Rep = std:: remove_cvref_t< FwdRep> >
+constexpr quantity< R{ } , Rep> operator ( ) ( FwdRep& & lhs) const ;
+
Effects : Equivalent to:
+return quantity{ std:: forward< FwdRep> ( lhs) , R{ } } ;
template < Quantity To, typename FwdFrom, Quantity From = std:: remove_cvref_t< FwdFrom> >
+ requires see below
+constexpr To sudo-cast ( FwdFrom& & q) ;
+
value_ cast is an explicit cast that allows truncation
. template < Unit auto ToU, typename FwdQ, Quantity Q = std:: remove_cvref_t< FwdQ> >
+ requires ( convertible( Q:: reference, ToU) )
+constexpr Quantity auto value_cast( FwdQ& & q) ;
+
Effects : Equivalent to:
+return sudo-cast < quantity< make-reference ( Q:: quantity_spec, ToU) , typename Q:: rep> > (
+ std:: forward< FwdQ> ( q) ) ;
+
template < Representation ToRep, typename FwdQ, Quantity Q = std:: remove_cvref_t< FwdQ> >
+ requires RepresentationOf < ToRep, Q:: quantity_spec> & &
+ std:: constructible_from< ToRep, typename Q:: rep>
+constexpr quantity< Q:: reference, ToRep> value_cast( FwdQ& & q) ;
+
Effects : Equivalent to:
+return sudo-cast < quantity< Q:: reference, ToRep> > ( std:: forward< FwdQ> ( q) ) ;
+
template < Unit auto ToU, Representation ToRep, typename FwdQ,
+ Quantity Q = std:: remove_cvref_t< FwdQ> >
+ requires see below
+constexpr Quantity auto value_cast( FwdQ& & q) ;
+template < Representation ToRep, Unit auto ToU, typename FwdQ,
+ Quantity Q = std:: remove_cvref_t< FwdQ> >
+ requires see below
+constexpr Quantity auto value_cast( FwdQ& & q) ;
+
Effects : Equivalent to:
+return sudo-cast < quantity< make-reference ( Q:: quantity_spec, ToU) , ToRep> > (
+ std:: forward< FwdQ> ( q) ) ;
+
Remarks : The expression in the
requires-clause is equivalent to:
+
( convertible( Q:: reference, ToU) ) & & RepresentationOf < ToRep, Q:: quantity_spec> & &
+std:: constructible_from< ToRep, typename Q:: rep>
+template < Quantity ToQ, typename FwdQ, Quantity Q = std:: remove_cvref_t< FwdQ> >
+ requires ( convertible( Q:: reference, ToQ:: unit) ) & & ( ToQ:: quantity_spec = = Q:: quantity_spec) & &
+ std:: constructible_from< typename ToQ:: rep, typename Q:: rep>
+constexpr Quantity auto value_cast( FwdQ& & q) ;
+
Effects : Equivalent to: return sudo-cast < ToQ> ( std:: forward< FwdQ> ( q) ) ;
quantity_ cast is an explicit cast that allows converting to more specific quantities
. [
Example 1 :
auto length = isq:: length( 42 * m) ;
+auto distance = quantity_cast< isq:: distance> ( length) ;
+ —
end example ]
template < QuantitySpec auto ToQS, typename FwdQ, Quantity Q = std:: remove_cvref_t< FwdQ> >
+ requires QuantitySpecCastableTo < Q:: quantity_spec, ToQS>
+constexpr Quantity auto quantity_cast( FwdQ& & q) ;
+
Effects : Equivalent to:
+return quantity{ std:: forward< FwdQ> ( q) . numerical-value , make-reference ( ToQS, Q:: unit) } ;
+
template < mp_units:: Quantity Q1, mp_units:: Quantity Q2>
+ requires requires {
+ { mp_units:: get_common_reference( Q1:: reference, Q2:: reference) } - > mp_units:: Reference;
+ typename std:: common_type_t< typename Q1:: rep, typename Q2:: rep> ;
+ requires mp_units:: RepresentationOf < std:: common_type_t< typename Q1:: rep, typename Q2:: rep> ,
+ mp_units:: get_common_quantity_spec( Q1:: quantity_spec,
+ Q2:: quantity_spec) > ;
+ }
+struct std:: common_type< Q1, Q2> {
+ using type = mp_units:: quantity< mp_units:: get_common_reference( Q1:: reference, Q2:: reference) ,
+ std:: common_type_t< typename Q1:: rep, typename Q2:: rep> > ;
+} ;
+
+template < mp_units:: Quantity Q, mp_units:: Representation Value>
+ requires ( Q:: unit = = mp_units:: one) & & requires {
+ typename mp_units:: quantity< Q:: reference, std:: common_type_t< typename Q:: rep, Value> > ;
+ }
+struct std:: common_type< Q, Value> {
+ using type = mp_units:: quantity< Q:: reference, std:: common_type_t< typename Q:: rep, Value> > ;
+} ;
+This subclause specifies the components
+for defining the origin of an affine space
. template < typename T>
+concept PointOrigin = SymbolicConstant < T> & & std:: derived_from< T, point-origin-interface > ;
+
+template < typename T, auto QS>
+concept PointOriginFor = PointOrigin < T> & & QuantitySpecOf < decltype ( QS) , T:: quantity-spec > ;
+
+template < typename T, auto V>
+concept SameAbsolutePointOriginAs =
+ PointOrigin < T> & & PointOrigin < decltype ( V) > & & same-absolute-point-origins ( T{ } , V) ;
+
An
absolute origin is an origin
+chosen by convention and not defined in terms of another origin
. A specialization of
absolute_ point_ origin is used as a base type when defining an absolute origin
. QS is the quantity the origin represents
. A specialization of
relative_ point_ origin is used as a base type when defining a relative origin
O . O is offset from
QP. absolute_ point_ origin by
QP. quantity_ from_ zero( ) . The member
quantity-spec is equal to
+
QP. point_ origin. quantity-spec if
+
QuantityKindSpec < decltype ( auto ( QP. quantity-spec ) ) >
+
+is satisfied, and
+to
QP. quantity-spec otherwise
. zeroth_ point_ origin_< QS> represents an origin
+chosen by convention as the value
0 of the quantity
QS . namespace mp_units {
+
+struct point-origin-interface {
+ template < PointOrigin PO, typename FwdQ,
+ QuantityOf < PO:: quantity-spec > Q = std:: remove_cvref_t< FwdQ> >
+ friend constexpr quantity_point< Q:: reference, PO{ } , typename Q:: rep> operator + ( PO, FwdQ& & q) ;
+ template < Quantity FwdQ, PointOrigin PO,
+ QuantityOf < PO:: quantity-spec > Q = std:: remove_cvref_t< FwdQ> >
+ friend constexpr quantity_point< Q:: reference, PO{ } , typename Q:: rep> operator + ( FwdQ& & q, PO) ;
+
+ template < PointOrigin PO, Quantity Q>
+ requires ReferenceOf < decltype ( auto ( Q:: reference) ) , PO:: quantity-spec >
+ friend constexpr QuantityPoint auto operator - ( PO po, const Q& q)
+ requires requires { - q; } ;
+
+ template < PointOrigin PO1, SameAbsolutePointOriginAs < PO1{ } > PO2>
+ requires see below
+ friend constexpr Quantity auto operator - ( PO1 po1, PO2 po2) ;
+
+ template < PointOrigin PO1, PointOrigin PO2>
+ friend consteval bool operator = = ( PO1 po1, PO2 po2) ;
+} ;
+
+}
+template < PointOrigin PO, typename FwdQ,
+ QuantityOf < PO:: quantity-spec > Q = std:: remove_cvref_t< FwdQ> >
+friend constexpr quantity_point< Q:: reference, PO{ } , typename Q:: rep> operator + ( PO, FwdQ& & q) ;
+template < Quantity FwdQ, PointOrigin PO,
+ QuantityOf < PO:: quantity-spec > Q = std:: remove_cvref_t< FwdQ> >
+friend constexpr quantity_point< Q:: reference, PO{ } , typename Q:: rep> operator + ( FwdQ& & q, PO) ;
+
Effects : Equivalent to:
+return quantity_ point{ std:: forward< FwdQ> ( q) , PO{ } } ;
Effects : Equivalent to:
+return po + - q;
template < PointOrigin PO1, SameAbsolutePointOriginAs < PO1{ } > PO2>
+ requires see below
+friend constexpr Quantity auto operator - ( PO1 po1, PO2 po2) ;
+
Effects : Equivalent to:
+if constexpr ( is-derived-from-specialization-of < PO1, absolute_point_origin> ( ) ) {
+ return po1 - po2. quantity-point ;
+} else if constexpr ( is-derived-from-specialization-of < PO2, absolute_point_origin> ( ) ) {
+ return po1. quantity-point - po2;
+} else {
+ return po1. quantity-point - po2. quantity-point ;
+}
+
Remarks : The expression in the
requires-clause is equivalent to:
+
QuantitySpecOf < decltype ( auto ( PO1:: quantity-spec ) ) , PO2:: quantity-spec > & &
+ ( is-derived-from-specialization-of < PO1, relative_point_origin> ( ) | |
+ is-derived-from-specialization-of < PO2, relative_point_origin> ( ) )
+Effects : Equivalent to:
+if constexpr ( is-derived-from-specialization-of < PO1, absolute_point_origin> ( ) & &
+ is-derived-from-specialization-of < PO2, absolute_point_origin> ( ) )
+ return std:: is_same_v< PO1, PO2> | |
+ ( is-specialization-of < PO1, zeroth_point_origin> ( ) & &
+ is-specialization-of < PO2, zeroth_point_origin> ( ) & &
+ interconvertible( po1. quantity-spec , po2. quantity-spec ) ) ;
+else if constexpr ( is-derived-from-specialization-of < PO1, relative_point_origin> ( ) & &
+ is-derived-from-specialization-of < PO2, relative_point_origin> ( ) )
+ return PO1:: quantity-point = = PO2:: quantity-point ;
+else if constexpr ( is-derived-from-specialization-of < PO1, relative_point_origin> ( ) )
+ return same-absolute-point-origins ( po1, po2) & &
+ is_eq_zero( PO1:: quantity-point . quantity_from_zero( ) ) ;
+else if constexpr ( is-derived-from-specialization-of < PO2, relative_point_origin> ( ) )
+ return same-absolute-point-origins ( po1, po2) & &
+ is_eq_zero( PO2:: quantity-point . quantity_from_zero( ) ) ;
+
Effects : Equivalent to:
+if constexpr ( is-derived-from-specialization-of < PO1, absolute_point_origin> ( ) & &
+ is-derived-from-specialization-of < PO2, absolute_point_origin> ( ) )
+ return po1 = = po2;
+else if constexpr ( is-derived-from-specialization-of < PO1, relative_point_origin> ( ) & &
+ is-derived-from-specialization-of < PO2, relative_point_origin> ( ) )
+ return po1. absolute-point-origin = = po2. absolute-point-origin ;
+else if constexpr ( is-derived-from-specialization-of < PO1, relative_point_origin> ( ) )
+ return po1. absolute-point-origin = = po2;
+else if constexpr ( is-derived-from-specialization-of < PO2, relative_point_origin> ( ) )
+ return po1 = = po2. absolute-point-origin ;
+else
+ return false ;
+
Effects : Equivalent to:
+if constexpr ( requires { get_unit( R{ } ) . point-origin ; } )
+ return get_unit( R{ } ) . point-origin ;
+else
+ return zeroth_point_origin< get_quantity_spec( R{ } ) > ;
+
template < typename T>
+concept QuantityPointLike =
+ ! QuantityPoint < T> & &
+ qty-like-impl < T, quantity_point_like_traits> & &
+ requires {
+ typename quantity_point< quantity_point_like_traits< T> :: reference,
+ quantity_point_like_traits< T> :: point_origin,
+ typename quantity_point_like_traits< T> :: rep> ;
+ } ;
+
namespace mp_units {
+
+template < typename T>
+concept QuantityPoint = ( is-derived-from-specialization-of < T, quantity_point> ( ) ) ;
+
+template < typename QP, auto V>
+concept QuantityPointOf =
+ QuantityPoint < QP> & & ( QuantitySpecOf < decltype ( auto ( QP:: quantity_spec) ) , V> | |
+ SameAbsolutePointOriginAs < decltype ( auto ( QP:: absolute_point_origin) ) , V> ) ;
+
+template < Reference auto R,
+ PointOriginFor < get_quantity_spec( R) > auto PO = default_point_origin( R) ,
+ RepresentationOf < get_quantity_spec( R) > Rep = double >
+class quantity_point {
+public :
+
+ static constexpr Reference auto reference = R;
+ static constexpr QuantitySpec auto quantity_spec = get_quantity_spec( reference) ;
+ static constexpr Dimension auto dimension = quantity_spec. dimension;
+ static constexpr Unit auto unit = get_unit( reference) ;
+ static constexpr PointOrigin auto absolute_point_origin = see below ;
+ static constexpr PointOrigin auto point_origin = PO;
+ using rep = Rep;
+ using quantity_type = quantity< reference, Rep> ;
+
+ quantity_type quantity-from-origin ;
+
+
+ static constexpr quantity_point min( ) noexcept
+ requires see below ;
+ static constexpr quantity_point max( ) noexcept
+ requires see below ;
+
+
+
+ quantity_point( ) = default ;
+ quantity_point( const quantity_point& ) = default ;
+ quantity_point( quantity_point& & ) = default ;
+ ~ quantity_point( ) = default ;
+
+ template < typename FwdQ, QuantityOf < quantity_spec> Q = std:: remove_cvref_t< FwdQ> >
+ requires std:: constructible_from< quantity_type, FwdQ> & &
+ ( point_origin = = default_point_origin( R) ) & &
+ ( implicitly_convertible( Q:: quantity_spec, quantity_spec) )
+ constexpr explicit quantity_point( FwdQ& & q) ;
+
+ template < typename FwdQ, QuantityOf < quantity_spec> Q = std:: remove_cvref_t< FwdQ> >
+ requires std:: constructible_from< quantity_type, FwdQ>
+ constexpr quantity_point( FwdQ& & q, decltype ( PO) ) ;
+
+ template < typename FwdQ, PointOrigin PO2,
+ QuantityOf < PO2:: quantity-spec > Q = std:: remove_cvref_t< FwdQ> >
+ requires std:: constructible_from< quantity_type, FwdQ> & & SameAbsolutePointOriginAs < PO2, PO>
+ constexpr quantity_point( FwdQ& & q, PO2) ;
+
+ template < QuantityPointOf < absolute_point_origin> QP>
+ requires std:: constructible_from< quantity_type, typename QP:: quantity_type>
+ constexpr explicit ( ! std:: convertible_to< typename QP:: quantity_type, quantity_type> )
+ quantity_point( const QP& qp) ;
+
+ template < QuantityPointLike QP>
+ requires see below
+ constexpr explicit ( see below ) quantity_point( const QP& qp) ;
+
+ quantity_point& operator = ( const quantity_point& ) = default ;
+ quantity_point& operator = ( quantity_point& & ) = default ;
+
+
+
+ template < SameAbsolutePointOriginAs < absolute_point_origin> NewPO>
+ constexpr QuantityPointOf < ( NewPO{ } ) > auto point_for( NewPO new_origin) const ;
+
+ template < UnitCompatibleWith < unit, quantity_spec> ToU>
+ requires see below
+ constexpr QuantityPointOf < quantity_spec> auto in( ToU) const ;
+
+ template < RepresentationOf < quantity_spec> ToRep>
+ requires see below
+ constexpr QuantityPointOf < quantity_spec> auto in( ) const ;
+
+ template < RepresentationOf < quantity_spec> ToRep,
+ UnitCompatibleWith < unit, quantity_spec> ToU>
+ requires see below
+ constexpr QuantityPointOf < quantity_spec> auto in( ToU) const ;
+
+ template < UnitCompatibleWith < unit, quantity_spec> ToU>
+ requires see below
+ constexpr QuantityPointOf < quantity_spec> auto force_in( ToU) const ;
+
+ template < RepresentationOf < quantity_spec> ToRep>
+ requires see below
+ constexpr QuantityPointOf < quantity_spec> auto force_in( ) const ;
+
+ template < RepresentationOf < quantity_spec> ToRep,
+ UnitCompatibleWith < unit, quantity_spec> ToU>
+ requires see below
+ constexpr QuantityPointOf < quantity_spec> auto force_in( ToU) const ;
+
+
+
+ template < PointOrigin PO2>
+ requires ( PO2{ } = = point_origin)
+ constexpr quantity_type& quantity_ref_from( PO2) & noexcept ;
+ template < PointOrigin PO2>
+ requires ( PO2{ } = = point_origin)
+ constexpr const quantity_type& quantity_ref_from( PO2) const & noexcept ;
+ template < PointOrigin PO2>
+ requires ( PO2{ } = = point_origin)
+ void quantity_ref_from( PO2) const & & = delete ;
+
+ template < PointOrigin PO2>
+ requires requires ( const quantity_point qp) { qp - PO2{ } ; }
+ constexpr Quantity auto quantity_from( PO2) const ;
+
+ template < QuantityPointOf < absolute_point_origin> QP>
+ constexpr Quantity auto quantity_from( const QP& ) const ;
+
+ constexpr Quantity auto quantity_from_zero( ) const ;
+
+
+ template < typename QP_, QuantityPointLike QP = std:: remove_cvref_t< QP_> >
+ requires see below
+ constexpr explicit ( see below ) operator QP_( ) const & noexcept ( see below ) ;
+ template < typename QP_, QuantityPointLike QP = std:: remove_cvref_t< QP_> >
+ requires see below
+ constexpr explicit ( see below ) operator QP_( ) & & noexcept ( see below ) ;
+
+
+
+ template < Mutable < quantity_point> QP>
+ friend constexpr decltype ( auto ) operator + + ( QP& & qp)
+ requires see below ;
+ template < Mutable < quantity_point> QP>
+ friend constexpr decltype ( auto ) operator - - ( QP& & qp)
+ requires see below ;
+
+ constexpr quantity_point operator + + ( int )
+ requires see below ;
+ constexpr quantity_point operator - - ( int )
+ requires see below ;
+
+
+ template < Mutable < quantity_point> QP, auto R2, typename Rep2>
+ requires see below
+ friend constexpr decltype ( auto ) operator + = ( QP& & qp, const quantity< R2, Rep2> & q) ;
+ template < Mutable < quantity_point> QP, auto R2, typename Rep2>
+ requires see below
+ friend constexpr decltype ( auto ) operator - = ( QP& & qp, const quantity< R2, Rep2> & q) ;
+
+
+
+ template < std:: derived_from< quantity_point> QP, auto R2, typename Rep2>
+ friend constexpr QuantityPoint auto operator + ( const QP& qp, const quantity< R2, Rep2> & q)
+ requires see below ;
+ template < std:: derived_from< quantity_point> QP, auto R2, typename Rep2>
+ friend constexpr QuantityPoint auto operator + ( const quantity< R2, Rep2> & q, const QP& qp)
+ requires see below ;
+ template < std:: derived_from< quantity_point> QP, auto R2, typename Rep2>
+ friend constexpr QuantityPoint auto operator - ( const QP& qp, const quantity< R2, Rep2> & q)
+ requires see below ;
+
+ template < std:: derived_from< quantity_point> QP, QuantityPointOf < absolute_point_origin> QP2>
+ friend constexpr Quantity auto operator - ( const QP& lhs, const QP2& rhs)
+ requires see below ;
+
+ template < std:: derived_from< quantity_point> QP, PointOrigin PO2>
+ requires see below
+ friend constexpr Quantity auto operator - ( const QP& qp, PO2 po) ;
+ template < std:: derived_from< quantity_point> QP, PointOrigin PO2>
+ requires see below
+ friend constexpr Quantity auto operator - ( PO2 po, const QP& qp) ;
+
+
+ template < std:: derived_from< quantity_point> QP, QuantityPointOf < absolute_point_origin> QP2>
+ requires see below
+ friend constexpr bool operator = = ( const QP& lhs, const QP2& rhs) ;
+ template < std:: derived_from< quantity_point> QP, QuantityPointOf < absolute_point_origin> QP2>
+ requires see below
+ friend constexpr auto operator < = > ( const QP& lhs, const QP2& rhs) ;
+} ;
+
+template < Quantity Q>
+explicit quantity_point( Q q)
+ - > quantity_point< Q:: reference, default_point_origin( Q:: reference) , typename Q:: rep> ;
+
+template < Quantity Q, PointOriginFor < Q:: quantity_spec> PO>
+quantity_point( Q, PO) - > quantity_point< Q:: reference, PO{ } , typename Q:: rep> ;
+
+template < QuantityPointLike QP, typename Traits = quantity_point_like_traits< QP> >
+explicit ( quantity_point_like_traits< QP> :: explicit_import) quantity_point( QP)
+ - > quantity_point< Traits:: reference, Traits:: point_origin, typename Traits:: rep> ;
+
+}
+The member
absolute_ point_ origin is equal to
PO if
+
is-derived-from-specialization-of < decltype ( PO) , absolute_point_origin> ( )
+
+is
true , and
+to
PO. quantity-point . absolute_ point_ origin otherwise
. static constexpr quantity_point min( ) noexcept
+ requires see below ;
+static constexpr quantity_point max( ) noexcept
+ requires see below ;
+
Let
F be one of
min and
max . Returns :
{ quantity_ type:: F ( ) , PO} . Remarks : The expression in the requires-clause is equivalent to:
+requires { quantity_type:: F ( ) ; }
+
template < typename FwdQ, QuantityOf < quantity_spec> Q = std:: remove_cvref_t< FwdQ> >
+ requires std:: constructible_from< quantity_type, FwdQ> & &
+ ( point_origin = = default_point_origin( R) ) & &
+ ( implicitly_convertible( Q:: quantity_spec, quantity_spec) )
+constexpr explicit quantity_point( FwdQ& & q) ;
+
+template < typename FwdQ, QuantityOf < quantity_spec> Q = std:: remove_cvref_t< FwdQ> >
+ requires std:: constructible_from< quantity_type, FwdQ>
+constexpr quantity_point( FwdQ& & q, decltype ( PO) ) ;
+
Effects : Initializes
quantity-from-origin with
std:: forward< FwdQ> ( q) . template < typename FwdQ, PointOrigin PO2,
+ QuantityOf < PO2:: quantity-spec > Q = std:: remove_cvref_t< FwdQ> >
+ requires std:: constructible_from< quantity_type, FwdQ> & & SameAbsolutePointOriginAs < PO2, PO>
+constexpr quantity_point( FwdQ& & q, PO2) ;
+
Effects : Equivalent to:
+quantity_point( quantity_point< Q:: reference, PO2{ } , typename Q:: rep> { std:: forward< FwdQ> ( q) ,
+ PO2{ } } )
+
template < QuantityPointOf < absolute_point_origin> QP>
+ requires std:: constructible_from< quantity_type, typename QP:: quantity_type>
+constexpr explicit ( ! std:: convertible_to< typename QP:: quantity_type, quantity_type> )
+ quantity_point( const QP& qp) ;
+
Effects : If
point_ origin = = QP:: point_ origin is
true ,
+initializes
quantity-from-origin with
qp. quantity_ ref_ from( point_ origin) . Otherwise, initializes
quantity-from-origin with
qp - point_ origin . template < QuantityPointLike QP>
+ requires see below
+constexpr explicit ( see below ) quantity_point( const QP& qp) ;
+
Let
Traits be
quantity_ point_ like_ traits< QP> . Effects : Initializes quantity-from-origin with
+Traits:: to_numerical_value( qp) , get_unit( Traits:: reference)
+
Remarks : The expression in the requires-clause is equivalent to:
+( Traits:: point_origin = = point_origin) & &
+ std:: convertible_to< quantity< Traits:: reference, typename Traits:: rep> , quantity_type>
+
+The expression inside explicit is equivalent to:
+Traits:: explicit_import | |
+ ! std:: convertible_to< quantity< Traits:: reference, typename Traits:: rep> , quantity_type>
+
template < SameAbsolutePointOriginAs < absolute_point_origin> NewPO>
+constexpr QuantityPointOf < ( NewPO{ } ) > auto point_for( NewPO new_origin) const ;
+
Effects : Equivalent to:
+if constexpr ( std:: is_same_v< NewPO, decltype ( point_origin) > )
+ return * this ;
+else
+ return :: mp_units:: quantity_point{ * this - new_origin, new_origin} ;
+
template < UnitCompatibleWith < unit, quantity_spec> ToU>
+ requires see below
+constexpr QuantityPointOf < quantity_spec> auto in( ToU) const ;
+
+template < RepresentationOf < quantity_spec> ToRep>
+ requires see below
+constexpr QuantityPointOf < quantity_spec> auto in( ) const ;
+
+template < RepresentationOf < quantity_spec> ToRep,
+ UnitCompatibleWith < unit, quantity_spec> ToU>
+ requires see below
+constexpr QuantityPointOf < quantity_spec> auto in( ToU) const ;
+
+template < UnitCompatibleWith < unit, quantity_spec> ToU>
+ requires see below
+constexpr QuantityPointOf < quantity_spec> auto force_in( ToU) const ;
+
+template < RepresentationOf < quantity_spec> ToRep>
+ requires see below
+constexpr QuantityPointOf < quantity_spec> auto force_in( ) const ;
+
+template < RepresentationOf < quantity_spec> ToRep,
+ UnitCompatibleWith < unit, quantity_spec> ToU>
+ requires see below
+constexpr QuantityPointOf < quantity_spec> auto force_in( ToU) const ;
+
Let
converted-quantity-expr be an expression denoting
+the function call to the corresponding member of
quantity_ ref_ from( point_ origin) . Effects : Equivalent to:
+return :: mp_units:: quantity_point{ converted-quantity-expr , point_origin} ;
+
Remarks : The expression in the requires-clause is equivalent to:
+requires { converted-quantity-expr ; }
+
template < PointOrigin PO2>
+ requires ( PO2{ } = = point_origin)
+constexpr quantity_type& quantity_ref_from( PO2) & noexcept ;
+template < PointOrigin PO2>
+ requires ( PO2{ } = = point_origin)
+constexpr const quantity_type& quantity_ref_from( PO2) const & noexcept ;
+
Returns :
quantity-from-origin . template < PointOrigin PO2>
+ requires requires ( const quantity_point qp) { qp - PO2{ } ; }
+constexpr Quantity auto quantity_from( PO2 rhs) const ;
+
+template < QuantityPointOf < absolute_point_origin> QP>
+constexpr Quantity auto quantity_from( const QP& rhs) const ;
+
Effects : Equivalent to:
+return * this - rhs;
constexpr Quantity auto quantity_from_zero( ) const ;
+
Effects : Equivalent to:
+if constexpr ( requires { unit. point-origin ; } ) {
+
+ const auto q = quantity_from( unit. point-origin ) ;
+ if constexpr ( requires { q. in( unit) ; } )
+
+ return q. in( unit) ;
+ else
+ return q;
+} else
+ return quantity_from( absolute_point_origin) ;
+
template < typename QP_, QuantityPointLike QP = std:: remove_cvref_t< QP_> >
+ requires see below
+constexpr explicit ( see below ) operator QP_( ) const & noexcept ( see below ) ;
+template < typename QP_, QuantityPointLike QP = std:: remove_cvref_t< QP_> >
+ requires see below
+constexpr explicit ( see below ) operator QP_( ) & & noexcept ( see below ) ;
+
Let
Traits be
quantity_ point_ like_ traits< QP> . Let result-expr be
+Traits:: from_numerical_value( std:: move( quantity-from-origin ) . numerical-value )
+
Remarks : The expression in the requires-clause is equivalent to:
+( point_origin = = Traits:: point_origin) & &
+ std:: convertible_to< quantity_type, quantity< Traits:: reference, typename Traits:: rep> >
+
+The expression inside explicit is equivalent to:
+Traits:: explicit_export | |
+ ! std:: convertible_to< quantity_type, quantity< Traits:: reference, typename Traits:: rep> >
+
+Let
T be
+
std:: is_ nothrow_ copy_ constructible_ v for the first signature, and
+
std:: is_ nothrow_ move_ constructible_ v for the second signature
. The exception specification is equivalent to:
+noexcept ( result-expr ) & & T < rep>
+
In the following descriptions,
+let
@ be the
operator . template < Mutable < quantity_point> QP>
+friend constexpr decltype ( auto ) operator + + ( QP& & qp)
+ requires see below ;
+template < Mutable < quantity_point> QP>
+friend constexpr decltype ( auto ) operator - - ( QP& & qp)
+ requires see below ;
+
Effects : Equivalent to
+
@qp. quantity-from-origin . Returns :
std:: forward< QP> ( qp) . Remarks : The expression in the requires-clause is equivalent to:
+requires { @qp. quantity-from-origin ; }
+
constexpr quantity_point operator + + ( int )
+ requires see below ;
+constexpr quantity_point operator - - ( int )
+ requires see below ;
+
Effects : Equivalent to:
+return { quantity-from-origin @, PO} ;
Remarks : The expression in the requires-clause is equivalent to:
+requires { quantity-from-origin @; }
+
template < Mutable < quantity_point> QP, auto R2, typename Rep2>
+ requires see below
+friend constexpr decltype ( auto ) operator + = ( QP& & qp, const quantity< R2, Rep2> & q) ;
+template < Mutable < quantity_point> QP, auto R2, typename Rep2>
+ requires see below
+friend constexpr decltype ( auto ) operator - = ( QP& & qp, const quantity< R2, Rep2> & q) ;
+
Effects : Equivalent to
+
qp. quantity-from-origin @ q . Returns :
std:: forward< QP> ( qp) . Remarks : The expression in the
requires-clause is equivalent to:
+
QuantityConvertibleTo < quantity< R2, Rep2> , quantity_type> & &
+ requires { qp. quantity-from-origin @ q; }
+In the following descriptions,
+let
@ be the
operator . template < std:: derived_from< quantity_point> QP, auto R2, typename Rep2>
+friend constexpr QuantityPoint auto operator + ( const QP& qp, const quantity< R2, Rep2> & q)
+ requires see below ;
+template < std:: derived_from< quantity_point> QP, auto R2, typename Rep2>
+friend constexpr QuantityPoint auto operator + ( const quantity< R2, Rep2> & q, const QP& qp)
+ requires see below ;
+template < std:: derived_from< quantity_point> QP, auto R2, typename Rep2>
+friend constexpr QuantityPoint auto operator - ( const QP& qp, const quantity< R2, Rep2> & q)
+ requires see below ;
+
Effects : Equivalent to:
+if constexpr ( is-specialization-of < PO, zeroth_point_origin> ( ) )
+ return :: mp_units:: quantity_point{ qp. quantity_ref_from( PO) @ q} ;
+else
+ return :: mp_units:: quantity_point{ qp. quantity_ref_from( PO) @ q, PO} ;
+
Remarks : The expression in the
requires-clause is equivalent to:
+
ReferenceOf < decltype ( R2) , PO. quantity-spec > & & requires {
+ qp. quantity_ref_from( PO) @ q;
+}
+template < std:: derived_from< quantity_point> QP, QuantityPointOf < absolute_point_origin> QP2>
+friend constexpr Quantity auto operator - ( const QP& lhs, const QP2& rhs)
+ requires see below ;
+
Effects : Equivalent to:
+return lhs. quantity_ref_from( point_origin) - rhs. quantity_ref_from( QP2:: point_origin) +
+ ( lhs. point_origin - rhs. point_origin) ;
+
Remarks : The expression in the requires-clause is equivalent to:
+requires { lhs. quantity_ref_from( point_origin) - rhs. quantity_ref_from( QP2:: point_origin) ; }
+
Recommended practice : The subtraction of two equal origins is not evaluated
. template < std:: derived_from< quantity_point> QP, PointOrigin PO2>
+ requires see below
+friend constexpr Quantity auto operator - ( const QP& qp, PO2 po) ;
+template < std:: derived_from< quantity_point> QP, PointOrigin PO2>
+ requires see below
+friend constexpr Quantity auto operator - ( PO2 po, const QP& qp) ;
+
Effects : For the first signature,
+equivalent to:
+if constexpr ( point_origin = = po)
+ return qp. quantity_ref_from( point_origin) ;
+else if constexpr ( is-derived-from-specialization-of < PO2,
+ :: mp_units:: absolute_point_origin> ( ) ) {
+ return qp. quantity_ref_from( point_origin) + ( qp. point_origin - qp. absolute_point_origin) ;
+} else {
+ return qp. quantity_ref_from( point_origin) -
+ po. quantity-point . quantity_ref_from( po. quantity-point . point_origin) +
+ ( qp. point_origin - po. quantity-point . point_origin) ;
+}
+
+For the second signature,
+equivalent to: return - ( qp - po) ;
Remarks : The expression in the
requires-clause is equivalent to:
+
QuantityPointOf < quantity_point, PO2{ } > & &
+ ReferenceOf < decltype ( auto ( reference) ) , PO2:: quantity-spec >
+Recommended practice : The subtraction of two equal origins is not evaluated
. template < std:: derived_from< quantity_point> QP, QuantityPointOf < absolute_point_origin> QP2>
+ requires see below
+friend constexpr bool operator = = ( const QP& lhs, const QP2& rhs) ;
+template < std:: derived_from< quantity_point> QP, QuantityPointOf < absolute_point_origin> QP2>
+ requires see below
+friend constexpr auto operator < = > ( const QP& lhs, const QP2& rhs) ;
+
Let
@ be the
operator , and
+let
C be
+
std:: equality_ comparable_ with if
@ is
= = , and
+
std:: three_ way_ comparable_ with if
@ is
< = > . Effects : Equivalent to:
+return lhs - lhs. absolute_point_origin @ rhs - rhs. absolute_point_origin;
+
Remarks : The expression in the requires-clause is equivalent to:
+C < quantity_type, typename QP2:: quantity_type>
+
Recommended practice : If the origins are equal, instead evaluate
+lhs. quantity_ref_from( point_origin) @ rhs. quantity_ref_from( QP2:: point_origin)
+
namespace mp_units {
+
+template < Reference R>
+struct point_ {
+ template < typename FwdRep,
+ RepresentationOf < get_quantity_spec( R{ } ) > Rep = std:: remove_cvref_t< FwdRep> >
+ constexpr quantity_point< R{ } , default_point_origin( R{ } ) , Rep> operator ( ) ( FwdRep& & lhs) const ;
+} ;
+
+}
+template < typename FwdRep,
+ RepresentationOf < get_quantity_spec( R{ } ) > Rep = std:: remove_cvref_t< FwdRep> >
+constexpr quantity_point< R{ } , default_point_origin( R{ } ) , Rep> operator ( ) ( FwdRep& & lhs) const ;
+
Effects : Equivalent to:
+return quantity_ point{ quantity{ std:: forward< FwdRep> ( lhs) , R{ } } } ;
value_ cast is an explicit cast that allows truncation
. template < Unit auto ToU, typename FwdQP, QuantityPoint QP = std:: remove_cvref_t< FwdQP> >
+ requires ( convertible( QP:: reference, ToU) )
+constexpr QuantityPoint auto value_cast( FwdQP& & qp) ;
+
Effects : Equivalent to:
+return quantity_point{ value_cast< ToU> ( std:: forward< FwdQP> ( qp) . quantity-from-origin ) ,
+ QP:: point_origin} ;
+
template < Representation ToRep, typename FwdQP, QuantityPoint QP = std:: remove_cvref_t< FwdQP> >
+ requires RepresentationOf < ToRep, QP:: quantity_spec> & &
+ std:: constructible_from< ToRep, typename QP:: rep>
+constexpr quantity_point< QP:: reference, QP:: point_origin, ToRep> value_cast( FwdQP& & qp) ;
+
Effects : Equivalent to:
+return { value_cast< ToRep> ( std:: forward< FwdQP> ( qp) . quantity-from-origin ) , QP:: point_origin} ;
+
Effects : Equivalent to:
+return quantity_point{ value_cast< ToU, ToRep> ( std:: forward< FwdQP> ( qp) . quantity-from-origin ) ,
+ QP:: point_origin} ;
+
Remarks : The expression in the
requires-clause is equivalent to:
+
( convertible( QP:: reference, ToU) ) & & RepresentationOf < ToRep, QP:: quantity_spec> & &
+std:: constructible_from< ToRep, typename QP:: rep>
+template < Quantity ToQ, typename FwdQP, QuantityPoint QP = std:: remove_cvref_t< FwdQP> >
+ requires ( convertible( QP:: reference, ToQ:: unit) ) & & ( ToQ:: quantity_spec = = QP:: quantity_spec) & &
+ std:: constructible_from< typename ToQ:: rep, typename QP:: rep>
+constexpr QuantityPoint auto value_cast( FwdQP& & qp) ;
+
Effects : Equivalent to:
+return quantity_point{ value_cast< ToQ> ( std:: forward< FwdQP> ( qp) . quantity-from-origin ) ,
+ QP:: point_origin} ;
+
template < QuantityPoint ToQP, typename FwdQP, QuantityPoint QP = std:: remove_cvref_t< FwdQP> >
+ requires ( convertible( QP:: reference, ToQP:: unit) ) & &
+ ( ToQP:: quantity_spec = = QP:: quantity_spec) & &
+ ( same-absolute-point-origins ( ToQP:: point_origin, QP:: point_origin) ) & &
+ std:: constructible_from< typename ToQP:: rep, typename QP:: rep>
+constexpr QuantityPoint auto value_cast( FwdQP& & qp) ;
+
Effects : Equivalent to:
+return sudo-cast < ToQP> ( std:: forward< FwdQP> ( qp) ) ;
quantity_ cast is an explicit cast that allows converting to more specific quantities
. template < QuantitySpec auto ToQS, typename FwdQP, QuantityPoint QP = std:: remove_cvref_t< FwdQP> >
+ requires QuantitySpecCastableTo < QP:: quantity_spec, ToQS>
+constexpr QuantityPoint auto quantity_cast( FwdQP& & qp) ;
+
Effects : Equivalent to:
+return QP{ quantity_cast< ToQS> ( std:: forward< FwdQP> ( qp) . quantity_from_origin ) ,
+ QP:: point_origin} ;
+
5.9 std::chrono interoperability [qty.chrono] namespace mp_units {
+
+template < typename Period>
+consteval auto time-unit-from-chrono-period ( )
+{
+ using namespace si;
+
+ if constexpr ( is_same_v< Period, std:: chrono:: nanoseconds:: period> )
+ return nano< second> ;
+ else if constexpr ( is_same_v< Period, std:: chrono:: microseconds:: period> )
+ return micro< second> ;
+ else if constexpr ( is_same_v< Period, std:: chrono:: milliseconds:: period> )
+ return milli< second> ;
+ else if constexpr ( is_same_v< Period, std:: chrono:: seconds:: period> )
+ return second;
+ else if constexpr ( is_same_v< Period, std:: chrono:: minutes:: period> )
+ return minute;
+ else if constexpr ( is_same_v< Period, std:: chrono:: hours:: period> )
+ return hour;
+ else if constexpr ( is_same_v< Period, std:: chrono:: days:: period> )
+ return day;
+ else if constexpr ( is_same_v< Period, std:: chrono:: weeks:: period> )
+ return mag< 7 > * day;
+ else
+ return mag_ratio< Period:: num, Period:: den> * second;
+}
+
+template < typename Rep, typename Period>
+struct quantity_like_traits< std:: chrono:: duration< Rep, Period> > {
+ static constexpr auto reference = time-unit-from-chrono-period < Period> ( ) ;
+ static constexpr bool explicit_import = false ;
+ static constexpr bool explicit_export = false ;
+ using rep = Rep;
+ using T = std:: chrono:: duration< Rep, Period> ;
+
+ static constexpr rep to_numerical_value( const T & q) noexcept (
+ std:: is_nothrow_copy_constructible_v< rep> )
+ {
+ return q. count( ) ;
+ }
+
+ static constexpr T from_numerical_value( const rep& v) noexcept (
+ std:: is_nothrow_copy_constructible_v< rep> )
+ {
+ return T ( v) ;
+ }
+} ;
+
+template < typename Clock>
+struct chrono_point_origin_ final : absolute_point_origin< isq:: time> {
+ using clock = Clock;
+} ;
+
+template < typename Clock, typename Rep, typename Period>
+struct quantity_point_like_traits<
+ std:: chrono:: time_point< Clock, std:: chrono:: duration< Rep, Period> > > {
+ static constexpr auto reference = time-unit-from-chrono-period < Period> ( ) ;
+ static constexpr auto point_origin = chrono_point_origin< Clock> ;
+ static constexpr bool explicit_import = false ;
+ static constexpr bool explicit_export = false ;
+ using rep = Rep;
+ using T = std:: chrono:: time_point< Clock, std:: chrono:: duration< Rep, Period> > ;
+
+ static constexpr rep to_numerical_value( const T & tp) noexcept (
+ std:: is_nothrow_copy_constructible_v< rep> )
+ {
+ return tp. time_since_epoch( ) . count( ) ;
+ }
+
+ static constexpr T from_numerical_value( const rep& v) noexcept (
+ std:: is_nothrow_copy_constructible_v< rep> )
+ {
+ return T ( std:: chrono:: duration< Rep, Period> ( v) ) ;
+ }
+} ;
+
+}
+
\ No newline at end of file
diff --git a/HEAD/api_reference/gen/fulltoc.html b/HEAD/api_reference/gen/fulltoc.html
index b9e9f504..19bae7f8 100644
--- a/HEAD/api_reference/gen/fulltoc.html
+++ b/HEAD/api_reference/gen/fulltoc.html
@@ -11,4 +11,4 @@ h4 { margin: 0.1em 5pt 0.1em 5pt; border-bottom: 1px dashed rgba(0, 0, 0, 0.2);
h3 { border-bottom-color: #b0b0b05a; }
h4 { border-bottom-color: #b0b0b05a; }
}
-
mp-units Library Reference Documentations Contents
\ No newline at end of file
+
mp-units Library Reference Documentations Contents
\ No newline at end of file
diff --git a/HEAD/api_reference/gen/generalindex.html b/HEAD/api_reference/gen/generalindex.html
index 2eac41ef..1eea99a3 100644
--- a/HEAD/api_reference/gen/generalindex.html
+++ b/HEAD/api_reference/gen/generalindex.html
@@ -1 +1 @@
-
14882: Index
\ No newline at end of file
+
14882: Index
\ No newline at end of file
diff --git a/HEAD/api_reference/gen/get.common.qty.spec.html b/HEAD/api_reference/gen/get.common.qty.spec.html
new file mode 100644
index 00000000..6b8ee4b6
--- /dev/null
+++ b/HEAD/api_reference/gen/get.common.qty.spec.html
@@ -0,0 +1,45 @@
+
[get.common.qty.spec] 5 Quantities and units library [quantities] Let
+
q1 be qs. . . [ 0 ] ,q2 be qs. . . [ 1 ] ,Q1 be decltype ( q1) ,Q2 be decltype ( q2) , andrest be a pack denoting the elements of qs without q1 and q2 . Effects : Equivalent to:
+
if constexpr ( sizeof . . . ( qs) = = 1 )
+ return q1;
+else if constexpr ( sizeof . . . ( qs) = = 2 ) {
+ using QQ1 = decltype ( remove-kind ( q1) ) ;
+ using QQ2 = decltype ( remove-kind ( q2) ) ;
+
+ if constexpr ( std:: is_same_v< Q1, Q2> )
+ return q1;
+ else if constexpr ( NestedQuantityKindSpecOf < Q1{ } , Q2{ } > )
+ return QQ1{ } ;
+ else if constexpr ( NestedQuantityKindSpecOf < Q2{ } , Q1{ } > )
+ return QQ2{ } ;
+ else if constexpr ( ( QuantityKindSpec < Q1> & & ! QuantityKindSpec < Q2> ) | |
+ ( DerivedQuantitySpec < QQ1> & & NamedQuantitySpec < QQ2> & &
+ implicitly_convertible( Q1{ } , Q2{ } ) ) )
+ return q2;
+ else if constexpr ( ( ! QuantityKindSpec < Q1> & & QuantityKindSpec < Q2> ) | |
+ ( NamedQuantitySpec < QQ1> & & DerivedQuantitySpec < QQ2> & &
+ implicitly_convertible( Q2{ } , Q1{ } ) ) )
+ return q1;
+ else if constexpr ( constexpr auto common_base = get-common-base < Q1{ } , Q2{ } > ( ) )
+ return * common_base;
+ else if constexpr ( implicitly_convertible( Q1{ } , Q2{ } ) )
+ return q2;
+ else if constexpr ( implicitly_convertible( Q2{ } , Q1{ } ) )
+ return q1;
+ else if constexpr ( implicitly_convertible( get-kind-tree-root ( Q1{ } ) ,
+ get-kind-tree-root ( Q2{ } ) ) )
+ return get-kind-tree-root ( q2) ;
+ else
+ return get-kind-tree-root ( q1) ;
+} else
+ return get_common_quantity_spec( get_common_quantity_spec( q1, q2) , rest. . . ) ;
+Remarks : The expression in the
requires-clause is equivalent to:
+
( sizeof . . . ( qs) ! = 0 & &
+ ( sizeof . . . ( qs) = = 1 | |
+ ( sizeof . . . ( qs) = = 2 & &
+ ( QuantitySpecConvertibleTo < get-kind-tree-root ( Q1{ } ) , get-kind-tree-root ( Q2{ } ) > | |
+ QuantitySpecConvertibleTo < get-kind-tree-root ( Q2{ } ) , get-kind-tree-root ( Q1{ } ) > ) ) | |
+ requires { get_common_quantity_spec( get_common_quantity_spec( q1, q2) , rest. . . ) ; } ) )
+
\ No newline at end of file
diff --git a/HEAD/api_reference/gen/impldefindex.html b/HEAD/api_reference/gen/impldefindex.html
new file mode 100644
index 00000000..19032070
--- /dev/null
+++ b/HEAD/api_reference/gen/impldefindex.html
@@ -0,0 +1 @@
+
14882: Index of implementation-defined behavior Index of implementation-defined behavior
\ No newline at end of file
diff --git a/HEAD/api_reference/gen/index.html b/HEAD/api_reference/gen/index.html
index eac15a2b..ce61df26 100644
--- a/HEAD/api_reference/gen/index.html
+++ b/HEAD/api_reference/gen/index.html
@@ -12,4 +12,4 @@ div.tocChapter { display: none; }
h3 { border-bottom-color: #b0b0b05a; }
h4 { border-bottom-color: #b0b0b05a; }
}
-
mp-units Library Reference Documentations Contents