mirror of
https://github.com/mpusz/mp-units.git
synced 2025-07-30 02:17:16 +02:00
feat: added an option to disable space before unit symbol in the text output
Resolves #387
This commit is contained in:
@ -13,7 +13,36 @@ any quantity in the most user-friendly way.
|
||||
a much better solution, but the library does not have enough information to print it that way by itself.
|
||||
|
||||
|
||||
## Output Streams
|
||||
## Customization point
|
||||
|
||||
The [SI Brochure](../appendix/references.md#SIBrochure) says:
|
||||
|
||||
!!! quote "SI Brochure"
|
||||
|
||||
The numerical value always precedes the unit and a space is always used to separate the unit from
|
||||
the number. ... The only exceptions to this rule are for the unit symbols for degree, minute and
|
||||
second for plane angle, `°`, `′` and `″`, respectively, for which no space is left between the
|
||||
numerical value and the unit symbol.
|
||||
|
||||
To support the above, the library exposes `space_before_unit_symbol` customization point. By default,
|
||||
its value is `true` for all the units, so the space between a number and a unit will be present in the
|
||||
output text. To change this behavior, we have to provide a partial specialization for a specific unit:
|
||||
|
||||
```cpp
|
||||
template<>
|
||||
inline constexpr bool space_before_unit_symbol<non_si::degree> = false;
|
||||
```
|
||||
|
||||
!!! note
|
||||
|
||||
The above works only for [the default formatting](#default-formatting). In case we provide our own
|
||||
format specification (i.e. `std::format("{:%Q %q}", q)`), the library will always obey this
|
||||
specification for all the units (no matter of what is the actual value of the
|
||||
`space_before_unit_symbol` customization point) and the separating space will always be present
|
||||
in this case.
|
||||
|
||||
|
||||
## Output streams
|
||||
|
||||
!!! tip
|
||||
|
||||
|
@ -398,7 +398,7 @@ private:
|
||||
// default format should print value followed by the unit separated with 1 space
|
||||
out = mp_units::detail::format_units_quantity_value<CharT>(out, q.numerical_value(), specs.rep, ctx.locale());
|
||||
if constexpr (mp_units::detail::has_unit_symbol(get_unit(Reference))) {
|
||||
*out++ = CharT(' ');
|
||||
if constexpr (mp_units::space_before_unit_symbol<get_unit(Reference)>) *out++ = CharT(' ');
|
||||
out = unit_symbol_to<CharT>(out, get_unit(Reference));
|
||||
}
|
||||
} else {
|
||||
|
@ -40,7 +40,7 @@ void to_stream(std::basic_ostream<CharT, Traits>& os, const quantity<R, Rep>& q)
|
||||
else
|
||||
os << q.numerical_value();
|
||||
if constexpr (has_unit_symbol(get_unit(R))) {
|
||||
os << " ";
|
||||
if constexpr (space_before_unit_symbol<get_unit(R)>) os << " ";
|
||||
unit_symbol_to<CharT>(std::ostream_iterator<CharT>(os), get_unit(R));
|
||||
}
|
||||
}
|
||||
|
@ -807,6 +807,15 @@ constexpr Out unit_symbol_impl(Out out, const derived_unit<Expr...>&, unit_symbo
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
* @brief Puts a space ' ' sign before a unit symbol
|
||||
*
|
||||
* Quantities of some units (e.g. degree, arcminute, arcsecond) should not be printed with the
|
||||
* space between a number and a unit. For those a partial specialization with the value `false` should
|
||||
* be provided.
|
||||
*/
|
||||
template<Unit auto U>
|
||||
inline constexpr bool space_before_unit_symbol = true;
|
||||
|
||||
template<typename CharT = char, std::output_iterator<CharT> Out, Unit U>
|
||||
constexpr Out unit_symbol_to(Out out, U u, unit_symbol_formatting fmt = unit_symbol_formatting{})
|
||||
|
@ -123,4 +123,11 @@ inline constexpr bool unit_can_be_prefixed<non_si::hour> = false;
|
||||
template<>
|
||||
inline constexpr bool unit_can_be_prefixed<non_si::day> = false;
|
||||
|
||||
template<>
|
||||
inline constexpr bool space_before_unit_symbol<non_si::degree> = false;
|
||||
template<>
|
||||
inline constexpr bool space_before_unit_symbol<non_si::arcminute> = false;
|
||||
template<>
|
||||
inline constexpr bool space_before_unit_symbol<non_si::arcsecond> = false;
|
||||
|
||||
} // namespace mp_units
|
||||
|
@ -236,6 +236,45 @@ TEST_CASE("operator<< on a quantity", "[text][ostream][fmt]")
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("no space before unit symbol")
|
||||
{
|
||||
SECTION("degree")
|
||||
{
|
||||
const auto q = 42 * deg;
|
||||
os << q;
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "42°"); }
|
||||
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(MP_UNITS_STD_FMT::format("{}", q) == os.str()); }
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(MP_UNITS_STD_FMT::format("{:%Q %q}", q) == "42 °"); }
|
||||
}
|
||||
|
||||
SECTION("arcminute")
|
||||
{
|
||||
const auto q = 42 * arcmin;
|
||||
os << q;
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "42′"); }
|
||||
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(MP_UNITS_STD_FMT::format("{}", q) == os.str()); }
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(MP_UNITS_STD_FMT::format("{:%Q %q}", q) == "42 ′"); }
|
||||
}
|
||||
|
||||
SECTION("arcsecond")
|
||||
{
|
||||
const auto q = 42 * arcsec;
|
||||
os << q;
|
||||
|
||||
SECTION("iostream") { CHECK(os.str() == "42″"); }
|
||||
|
||||
SECTION("fmt with default format {} on a quantity") { CHECK(MP_UNITS_STD_FMT::format("{}", q) == os.str()); }
|
||||
|
||||
SECTION("fmt with format {:%Q %q} on a quantity") { CHECK(MP_UNITS_STD_FMT::format("{:%Q %q}", q) == "42 ″"); }
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("8-bit integers")
|
||||
{
|
||||
SECTION("signed positive")
|
||||
|
Reference in New Issue
Block a user