// The MIT License (MIT) // // Copyright (c) 2018 Mateusz Pusz // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #include "test_tools.h" #include #include #include #include #include namespace { using namespace units; using namespace units::detail; using one_ = struct one; // base dimensions // clang-format off inline constexpr struct dim_length_ : base_dimension<"L"> {} dim_length; inline constexpr struct dim_mass_ : base_dimension<"M"> {} dim_mass; inline constexpr struct dim_time_ : base_dimension<"T"> {} dim_time; inline constexpr struct dim_thermodynamic_temperature_ : base_dimension {} dim_thermodynamic_temperature; // quantities specification QUANTITY_SPEC_(length, dim_length); QUANTITY_SPEC_(mass, dim_mass); QUANTITY_SPEC_(time, dim_time); QUANTITY_SPEC_(thermodynamic_temperature, dim_thermodynamic_temperature); // base units inline constexpr struct second_ : named_unit<"s", time> {} second; inline constexpr struct metre_ : named_unit<"m", length> {} metre; inline constexpr struct gram_ : named_unit<"g", mass> {} gram; inline constexpr struct kilogram_ : decltype(si::kilo) {} kilogram; inline constexpr struct kelvin_ : named_unit<"K", thermodynamic_temperature> {} kelvin; // hypothetical natural units for c=1 inline constexpr struct nu_second_ : named_unit<"s"> {} nu_second; // derived named units inline constexpr struct radian_ : named_unit<"rad", metre / metre> {} radian; inline constexpr struct steradian_ : named_unit<"sr", square / square> {} steradian; inline constexpr struct hertz_ : named_unit<"Hz", 1 / second> {} hertz; inline constexpr struct becquerel_ : named_unit<"Bq", 1 / second> {} becquerel; inline constexpr struct newton_ : named_unit<"N", kilogram * metre / square> {} newton; inline constexpr struct pascal_ : named_unit<"Pa", newton / square> {} pascal; inline constexpr struct joule_ : named_unit<"J", newton * metre> {} joule; inline constexpr struct watt_ : named_unit<"W", joule / second> {} watt; inline constexpr struct degree_Celsius_ : named_unit {} degree_Celsius; inline constexpr struct minute_ : named_unit<"min", mag<60> * second> {} minute; inline constexpr struct hour_ : named_unit<"h", mag<60> * minute> {} hour; inline constexpr struct day_ : named_unit<"d", mag<24> * hour> {} day; inline constexpr struct astronomical_unit_ : named_unit<"au", mag<149'597'870'700> * metre> {} astronomical_unit; inline constexpr struct degree_ : named_unit * radian> {} degree; inline constexpr struct are_ : named_unit<"a", square>> {} are; inline constexpr struct hectare_ : decltype(si::hecto) {} hectare; inline constexpr struct litre_ : named_unit<"l", cubic>> {} litre; inline constexpr struct tonne_ : named_unit<"t", mag<1000> * kilogram> {} tonne; inline constexpr struct dalton_ : named_unit<"Da", mag * mag_power<10, -27> * kilogram> {} dalton; inline constexpr struct electronvolt_ : named_unit<"eV", mag * mag_power<10, -19> * joule> {} electronvolt; inline constexpr struct yard_ : named_unit<"yd", mag * metre> {} yard; inline constexpr struct foot_ : named_unit<"ft", mag * yard> {} foot; inline constexpr struct mile_ : named_unit<"mi", mag<1760> * yard> {} mile; inline constexpr struct kilometre_ : decltype(si::kilo) {} kilometre; inline constexpr struct kilojoule_ : decltype(si::kilo) {} kilojoule; // physical constant units inline constexpr struct standard_gravity_unit_ : constant_unit<"g", mag * metre / square> {} standard_gravity_unit; inline constexpr struct speed_of_light_in_vacuum_unit_ : constant_unit<"c", mag<299'792'458> * metre / second> {} speed_of_light_in_vacuum_unit; // clang-format on // concepts verification static_assert(Unit); static_assert(Unit); static_assert(Unit); static_assert(Unit); static_assert(Unit); static_assert(Unit); static_assert(Unit); static_assert(Unit)>); static_assert(Unit)>); static_assert(Unit)>); static_assert(Unit * second)>); static_assert(Unit); static_assert(Unit); static_assert(Unit); static_assert(Unit); static_assert(Unit); static_assert(NamedUnit); static_assert(NamedUnit); static_assert(NamedUnit); static_assert(NamedUnit); static_assert(NamedUnit); static_assert(!NamedUnit); static_assert(!NamedUnit); static_assert(!NamedUnit); static_assert(!NamedUnit)>); static_assert(!NamedUnit)>); static_assert(!NamedUnit)>); static_assert(!NamedUnit * second)>); static_assert(!NamedUnit); // named unit static_assert(is_of_type); static_assert(is_of_type); static_assert(get_canonical_unit(metre).mag == mag<1>); static_assert(interconvertible(metre, metre)); static_assert(!interconvertible(metre, second)); static_assert(metre == metre); static_assert(metre != second); static_assert(is_of_type); static_assert(is_of_type); static_assert(get_canonical_unit(degree_Celsius).mag == mag<1>); static_assert(interconvertible(degree_Celsius, kelvin)); static_assert(degree_Celsius == kelvin); static_assert(is_of_type); static_assert(is_of_type); static_assert(get_canonical_unit(radian).mag == mag<1>); static_assert(is_of_type); static_assert(is_of_type); static_assert(get_canonical_unit(degree).mag == mag_pi / mag<180>); static_assert(interconvertible(radian, degree)); static_assert(radian != degree); static_assert(is_of_type); static_assert(is_of_type); static_assert(get_canonical_unit(steradian).mag == mag<1>); static_assert(interconvertible(radian, steradian)); // !!! static_assert(radian == steradian); // !!! static_assert(is_of_type); static_assert(is_of_type); static_assert(get_canonical_unit(minute).mag == mag<60>); static_assert(interconvertible(minute, second)); static_assert(minute != second); static_assert(is_of_type); static_assert(is_of_type); static_assert(get_canonical_unit(hour).mag == mag<3600>); static_assert(interconvertible(hour, second)); static_assert(interconvertible(hour, minute)); static_assert(interconvertible(hour, hour)); static_assert(hour != second); static_assert(hour != minute); static_assert(hour == hour); static_assert(is_of_type); static_assert( is_of_type>>>); static_assert(get_canonical_unit(newton).mag == mag<1000>); // !!! (because of kilogram) static_assert(interconvertible(newton, newton)); static_assert(newton == newton); static_assert(is_of_type); static_assert( is_of_type, per>>>); static_assert(get_canonical_unit(joule).mag == mag<1000>); // !!! (because of kilogram) static_assert(interconvertible(joule, joule)); static_assert(joule == joule); static_assert(joule != newton); static_assert(is_of_type); // constant_unit static_assert(is_of_type); static_assert( is_of_type>>>); static_assert(get_canonical_unit(standard_gravity_unit).mag == mag); static_assert(interconvertible(standard_gravity_unit, standard_gravity_unit)); static_assert(interconvertible(standard_gravity_unit, metre / square)); static_assert(standard_gravity_unit == standard_gravity_unit); static_assert(standard_gravity_unit != metre / square); // magnitude is different static_assert(standard_gravity_unit.symbol == "[g]"); // prefixed_unit static_assert(is_of_type); static_assert(is_of_type); static_assert(get_canonical_unit(kilometre).mag == mag<1000>); static_assert(interconvertible(kilometre, metre)); static_assert(kilometre != metre); static_assert(kilometre.symbol == "km"); static_assert(is_of_type); static_assert(is_of_type, per>>>); static_assert(get_canonical_unit(kilojoule).mag == mag<1'000'000>); static_assert(interconvertible(kilojoule, joule)); static_assert(kilojoule != joule); static_assert(kilojoule.symbol == "kJ"); static_assert(is_of_type, si::kilo_>); static_assert(is_of_type, si::kilo_>); // TODO Should the below be a scaled version of metre^2? static_assert(is_of_type>); // !!! static_assert(is_of_type>>); // !!! // prefixes static_assert(si::yocto.symbol == "ym"); static_assert(si::zepto.symbol == "zm"); static_assert(si::atto.symbol == "am"); static_assert(si::femto.symbol == "fm"); static_assert(si::pico.symbol == "pm"); static_assert(si::nano.symbol == "nm"); static_assert(si::micro.symbol == basic_symbol_text{"µm", "um"}); static_assert(si::milli.symbol == "mm"); static_assert(si::centi.symbol == "cm"); static_assert(si::deci.symbol == "dm"); static_assert(si::deca.symbol == "dam"); static_assert(si::hecto.symbol == "hm"); static_assert(si::kilo.symbol == "km"); static_assert(si::mega.symbol == "Mm"); static_assert(si::giga.symbol == "Gm"); static_assert(si::tera.symbol == "Tm"); static_assert(si::peta.symbol == "Pm"); static_assert(si::exa.symbol == "Em"); static_assert(si::zetta.symbol == "Zm"); static_assert(si::yotta.symbol == "Ym"); // scaled_unit constexpr auto m_1 = mag<1> * metre; static_assert(is_of_type); static_assert(is_of_type); static_assert(get_canonical_unit(m_1).mag == mag<1>); constexpr auto m_2 = mag<2> * metre; static_assert(is_of_type, metre_>>); static_assert(is_of_type); static_assert(get_canonical_unit(m_2).mag == mag<2>); constexpr auto km_2 = mag<2> * kilometre; static_assert(is_of_type, kilometre_>>); static_assert(is_of_type); static_assert(get_canonical_unit(km_2).mag == mag<2000>); constexpr auto kJ_42 = mag<42> * si::kilo; static_assert(is_of_type, si::kilo_>>); static_assert( is_of_type, per>>>); static_assert(get_canonical_unit(kJ_42).mag == mag<42'000'000>); // derived unit expression template syntax verification static_assert(is_of_type<1 / second, derived_unit>>); static_assert(is_of_type<1 / (1 / second), second_>); static_assert(is_of_type); static_assert(is_of_type); static_assert(is_of_type>>); static_assert(is_of_type<1 / second * one, derived_unit>>); static_assert(is_of_type>); static_assert(is_of_type>>); static_assert(is_of_type, derived_unit>>); static_assert(is_of_type, derived_unit>>); static_assert(is_of_type * metre, derived_unit>>); static_assert(is_of_type, derived_unit>>); static_assert(is_of_type / metre, metre_>); static_assert(is_of_type / metre, derived_unit>>); static_assert(is_of_type / square, metre_>); static_assert(is_of_type>>); static_assert(is_of_type, derived_unit>>>); static_assert(is_of_type / second, derived_unit>>>); static_assert(is_of_type, second_>>); static_assert(is_of_type, second_>>); static_assert(is_of_type, second_>>); static_assert(is_of_type, second_>>); static_assert(is_of_type<1 / second * metre, derived_unit>>); static_assert(is_of_type<1 / second * second, one_>); static_assert(is_of_type); static_assert(is_of_type<1 / second / one, derived_unit>>); static_assert(is_of_type); static_assert(is_of_type<1 / second * (1 / second), derived_unit>>>); static_assert(is_of_type<1 / (second * second), derived_unit>>>); static_assert(is_of_type<1 / (1 / (second * second)), derived_unit>>); static_assert(is_of_type>>>); static_assert(is_of_type, per>>>); static_assert(is_of_type); static_assert(is_of_type>>); static_assert(is_of_type>>); static_assert(is_of_type>>); static_assert(is_of_type<1 / (1 / second), second_>); static_assert(is_of_type); static_assert(is_of_type<1 / pascal, derived_unit>>); static_assert(is_of_type<1 / gram * metre * square, derived_unit, per>>); static_assert(is_of_type<1 / (gram / (metre * square)), derived_unit, per>>); static_assert(is_of_type / gram), derived_unit, per>>); static_assert(is_of_type / gram, derived_unit, per>>); static_assert(is_of_type<(metre * square / gram) * one, derived_unit, per>>); static_assert(is_of_type / gram * one, derived_unit, per>>); static_assert(is_of_type>); static_assert(is_of_type>); static_assert(is_of_type>>); static_assert(is_of_type>>); static_assert(is_of_type); static_assert(is_of_type>); static_assert(is_of_type>); static_assert(std::is_same_v); static_assert(std::is_same_v); static_assert(std::is_same_v); static_assert(std::is_same_v); static_assert(std::is_same_v)>); // derived unit normalization constexpr auto m_per_s = metre / second; static_assert(is_of_type>>); static_assert(get_canonical_unit(m_per_s).mag == mag<1>); constexpr auto km_per_s = kilometre / second; static_assert(is_of_type>>); static_assert(is_of_type>>); static_assert(get_canonical_unit(km_per_s).mag == mag<1000>); constexpr auto km_per_h = kilometre / hour; static_assert(is_of_type>>); static_assert(is_of_type>>); static_assert(get_canonical_unit(km_per_h).mag == mag); static_assert(is_of_type>>); static_assert(is_of_type); static_assert( is_of_type>>>); static_assert( is_of_type, per>>); static_assert( is_of_type>>>); static_assert(get_canonical_unit(standard_gravity_unit).mag == mag); static_assert(is_of_type>>>); static_assert(is_of_type>>); // operations commutativity constexpr auto u1 = mag<1000> * kilometre / hour; static_assert(is_of_type, derived_unit>>>); static_assert(is_of_type>>); static_assert(get_canonical_unit(u1).mag == mag); constexpr auto u2 = mag<1000> * (kilometre / hour); static_assert(is_of_type, derived_unit>>>); static_assert(is_of_type>>); static_assert(get_canonical_unit(u2).mag == mag); constexpr auto u3 = 1 / hour * (mag<1000> * kilometre); static_assert(is_of_type, derived_unit>>>); static_assert(is_of_type>>); static_assert(get_canonical_unit(u3).mag == mag); template concept invalid_operations = requires { requires !requires { s < s; }; requires !requires { s / 2; }; requires !requires { 2 * s; }; requires !requires { s * 2; }; requires !requires { s + 2; }; requires !requires { 2 + s; }; requires !requires { s + s; }; requires !requires { s - 2; }; requires !requires { 2 - s; }; requires !requires { s - s; }; requires !requires { s == 2; }; requires !requires { 2 == s; }; requires !requires { s < 2; }; requires !requires { 2 < s; }; requires !requires { s + time[second]; }; requires !requires { s - time[second]; }; requires !requires { s* time[second]; }; requires !requires { s / time[second]; }; requires !requires { s == time[second]; }; requires !requires { s < time[second]; }; requires !requires { time[second] + s; }; requires !requires { time[second] - s; }; requires !requires { time[second] * s; }; requires !requires { time[second] / s; }; requires !requires { time[second] == s; }; requires !requires { time[second] < s; }; requires !requires { s + 1 * time[second]; }; requires !requires { s - 1 * time[second]; }; requires !requires { s * 1 * time[second]; }; requires !requires { s / 1 * time[second]; }; requires !requires { s == 1 * time[second]; }; requires !requires { s == 1 * time[second]; }; requires !requires { 1 * time[second] + s; }; requires !requires { 1 * time[second] - s; }; requires !requires { 1 * time[second] * s; }; requires !requires { 1 * time[second] == s; }; requires !requires { 1 * time[second] < s; }; }; static_assert(invalid_operations); // comparisons of the same units static_assert(second == second); static_assert(metre / second == metre / second); static_assert(si::milli / si::milli == si::micro / si::micro); static_assert(si::milli / si::micro == si::micro / si::nano); static_assert(si::micro / si::milli == si::nano / si::micro); static_assert(si::milli * si::kilo == si::deci * si::deca); static_assert(si::kilo * si::milli == si::deca * si::deci); // comparisons of equivalent units (named vs unnamed/derived) static_assert(1 / second == hertz); static_assert(interconvertible(1 / second, hertz)); // comparisons of equivalent units of different quantities static_assert(hertz == becquerel); static_assert(interconvertible(hertz, becquerel)); // comparisons of scaled units static_assert(si::kilo == kilometre); static_assert(mag<1000> * metre == si::kilo); static_assert(mag<1000> * metre == kilometre); static_assert(interconvertible(si::kilo, kilometre)); static_assert(interconvertible(mag<1000> * metre, si::kilo)); static_assert(interconvertible(mag<1000> * metre, kilometre)); static_assert(metre != kilometre); static_assert(interconvertible(metre, kilometre)); static_assert(mag<100> * metre != kilometre); static_assert(interconvertible(mag<100> * metre, kilometre)); static_assert(si::milli != kilometre); static_assert(interconvertible(si::milli, kilometre)); // comparisons of non-convertible units static_assert(metre != metre * metre); static_assert(!interconvertible(metre, metre* metre)); // one static_assert(is_of_type); static_assert(metre / metre == one); static_assert(hertz * second == one); static_assert(hertz == 1 / second); static_assert(newton == kilogram * metre / square); static_assert(joule == kilogram * square / square); static_assert(joule == newton * metre); static_assert(watt == joule / second); static_assert(watt == kilogram * square / cubic); // power static_assert(is_same_v(metre)), decltype(metre * metre)>); static_assert(is_same_v(kilometre)), decltype(kilometre * kilometre)>); static_assert(is_same_v(si::kilo)), decltype(si::kilo * si::kilo)>); static_assert(is_same_v(hour)), decltype(hour * hour)>); static_assert(is_same_v(mag<3600> * second)), decltype((mag<3600> * second) * (mag<3600> * second))>); static_assert(is_same_v(metre / second)), decltype(metre * metre / second / second)>); static_assert(is_same_v(kilometre / hour)), decltype(kilometre * kilometre / hour / hour)>); static_assert(is_of_type(metre), derived_unit>>); static_assert(is_of_type(metre), derived_unit>>); static_assert(is_of_type(metre* metre), metre_>); static_assert(is_of_type(metre* metre* metre), metre_>); static_assert(is_of_type(metre* metre), derived_unit>>); static_assert(is_of_type(metre / second), derived_unit, per>>>); static_assert(is_of_type(metre / (second * second)), derived_unit, per>>); static_assert(is_of_type>>); static_assert(is_of_type(kilometre), derived_unit>>); static_assert(is_of_type(si::kilo), derived_unit, 2>>>); static_assert(is_of_type(hour), derived_unit>>); static_assert( is_of_type(mag<3600>* second), scaled_unit * mag<3600>, derived_unit>>>); // common_type static_assert(is_of_type); static_assert(is_of_type); static_assert(is_of_type, kilogram), kilogram_>); static_assert(is_of_type), kilogram_>); static_assert(is_of_type* gram, kilogram), kilogram_>); static_assert(is_of_type* gram), kilogram_>); static_assert(is_of_type); static_assert(is_of_type); static_assert(is_of_type); static_assert(is_of_type); static_assert(is_of_type); static_assert(is_of_type); static_assert(is_of_type); static_assert(is_of_type); static_assert( is_of_type, si::milli), std::remove_const_t)>>); static_assert( is_of_type, si::kilo), std::remove_const_t)>>); static_assert(is_of_type); static_assert(is_of_type); // TODO The below have long/unreadable magnitude types static_assert(is_of_type, derived_unit>>>); static_assert(is_of_type, derived_unit>>>); static_assert(is_of_type, metre_>>); static_assert(is_of_type, metre_>>); static_assert( is_of_type>>); // unit symbols #ifdef __cpp_lib_constexpr_string using enum text_encoding; using enum unit_symbol_solidus; using enum unit_symbol_separator; // named units static_assert(unit_symbol(metre) == "m"); static_assert(unit_symbol(second) == "s"); static_assert(unit_symbol(joule) == "J"); static_assert(unit_symbol(degree_Celsius) == "\u00B0C"); static_assert(unit_symbol(degree_Celsius, {.encoding = ascii}) == "`C"); static_assert(unit_symbol(kilometre) == "km"); static_assert(unit_symbol(si::milli) == "mm"); static_assert(unit_symbol(si::micro) == "µm"); static_assert(unit_symbol(si::micro, {.encoding = ascii}) == "um"); static_assert(unit_symbol(kilojoule) == "kJ"); static_assert(unit_symbol(hour) == "h"); // scaled units static_assert(unit_symbol(mag<100> * metre) == "× 10² m"); static_assert(unit_symbol(mag<100> * metre, {.encoding = ascii}) == "x 10^2 m"); static_assert(unit_symbol(mag<60> * second) == "[6 × 10¹] s"); static_assert(unit_symbol(mag<60> * second, {.encoding = ascii}) == "[6 x 10^1] s"); // derived units static_assert(unit_symbol(one) == ""); static_assert(unit_symbol(percent) == "%"); static_assert(unit_symbol(per_mille) == "‰"); static_assert(unit_symbol(per_mille, {.encoding = ascii}) == "%o"); static_assert(unit_symbol(square) == "m²"); static_assert(unit_symbol(square, {.encoding = ascii}) == "m^2"); static_assert(unit_symbol(cubic) == "m³"); static_assert(unit_symbol(cubic, {.encoding = ascii}) == "m^3"); static_assert(unit_symbol(kilometre * metre) == "km m"); static_assert(unit_symbol(kilometre * metre, {.separator = dot}) == "km⋅m"); static_assert(unit_symbol(metre / metre) == ""); static_assert(unit_symbol(kilometre / metre) == "km/m"); static_assert(unit_symbol(kilometre / metre, {.solidus = never}) == "km m⁻¹"); static_assert(unit_symbol(kilometre / metre, {.encoding = ascii, .solidus = never}) == "km m^-1"); static_assert(unit_symbol(metre / second) == "m/s"); static_assert(unit_symbol(metre / second, {.solidus = always}) == "m/s"); static_assert(unit_symbol(metre / second, {.solidus = never}) == "m s⁻¹"); static_assert(unit_symbol(metre / second, {.encoding = ascii, .solidus = never}) == "m s^-1"); static_assert(unit_symbol(metre / second, {.solidus = never, .separator = dot}) == "m⋅s⁻¹"); static_assert(unit_symbol(metre / square) == "m/s²"); static_assert(unit_symbol(metre / square, {.encoding = ascii}) == "m/s^2"); static_assert(unit_symbol(metre / square, {.solidus = always}) == "m/s²"); static_assert(unit_symbol(metre / square, {.encoding = ascii, .solidus = always}) == "m/s^2"); static_assert(unit_symbol(metre / square, {.solidus = never}) == "m s⁻²"); static_assert(unit_symbol(metre / square, {.encoding = ascii, .solidus = never}) == "m s^-2"); static_assert(unit_symbol(metre / square, {.solidus = never, .separator = dot}) == "m⋅s⁻²"); static_assert(unit_symbol(kilogram * metre / square) == "kg m/s²"); static_assert(unit_symbol(kilogram * metre / square, {.separator = dot}) == "kg⋅m/s²"); static_assert(unit_symbol(kilogram * metre / square, {.encoding = ascii}) == "kg m/s^2"); static_assert(unit_symbol(kilogram * metre / square, {.solidus = always}) == "kg m/s²"); static_assert(unit_symbol(kilogram * metre / square, {.encoding = ascii, .solidus = always}) == "kg m/s^2"); static_assert(unit_symbol(kilogram * metre / square, {.solidus = never}) == "kg m s⁻²"); static_assert(unit_symbol(kilogram * metre / square, {.encoding = ascii, .solidus = never}) == "kg m s^-2"); static_assert(unit_symbol(kilogram * metre / square, {.solidus = never, .separator = dot}) == "kg⋅m⋅s⁻²"); static_assert(unit_symbol(kilogram / metre / square) == "kg m⁻¹ s⁻²"); static_assert(unit_symbol(kilogram / metre / square, {.separator = dot}) == "kg⋅m⁻¹⋅s⁻²"); static_assert(unit_symbol(kilogram / metre / square, {.encoding = ascii}) == "kg m^-1 s^-2"); static_assert(unit_symbol(kilogram / metre / square, {.solidus = always}) == "kg/(m s²)"); static_assert(unit_symbol(kilogram / metre / square, {.encoding = ascii, .solidus = always}) == "kg/(m s^2)"); static_assert(unit_symbol(kilogram / metre / square, {.solidus = never}) == "kg m⁻¹ s⁻²"); static_assert(unit_symbol(kilogram / metre / square, {.encoding = ascii, .solidus = never}) == "kg m^-1 s^-2"); static_assert(unit_symbol(kilogram / metre / square, {.solidus = never, .separator = dot}) == "kg⋅m⁻¹⋅s⁻²"); static_assert(unit_symbol(pow<123>(metre)) == "m¹²³"); static_assert(unit_symbol(pow<1, 2>(metre)) == "m^(1/2)"); static_assert(unit_symbol(pow<3, 5>(metre)) == "m^(3/5)"); static_assert(unit_symbol(pow<1, 2>(metre / second)) == "m^(1/2)/s^(1/2)"); // Physical constants static_assert(unit_symbol(speed_of_light_in_vacuum_unit) == "[c]"); static_assert(unit_symbol(gram * standard_gravity_unit * speed_of_light_in_vacuum_unit) == "[c] [g] g"); static_assert(unit_symbol(gram / standard_gravity_unit) == "g/[g]"); #endif // __cpp_lib_constexpr_string } // namespace