When #1341 implemented operator<<(basic_ostream&, const duration&), its unit suffix logic handled only char and wchar_t:
|
#define _IF_PERIOD_RETURN_SUFFIX_ELSE(_TYPE, _SUFFIX) \
|
|
if constexpr (is_same_v<_Period, _TYPE>) { \
|
|
if constexpr (is_same_v<_CharT, char>) { \
|
|
return _SUFFIX; \
|
|
} else { \
|
|
return L##_SUFFIX; \
|
|
} \
|
|
} else
|
|
|
|
template <class _CharT, class _Period>
|
|
_NODISCARD constexpr const _CharT* _Get_literal_unit_suffix() {
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(atto, "as")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(femto, "fs")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(pico, "ps")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(nano, "ns")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(micro, "us")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(milli, "ms")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(centi, "cs")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(deci, "ds")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(seconds::period, "s")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(deca, "das")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(hecto, "hs")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(kilo, "ks")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(mega, "Ms")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(giga, "Gs")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(tera, "Ts")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(peta, "Ps")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(exa, "Es")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(minutes::period, "min")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(hours::period, "h")
|
|
_IF_PERIOD_RETURN_SUFFIX_ELSE(ratio<86400>, "d")
|
|
|
|
{
|
|
return nullptr;
|
|
}
|
|
}
|
|
|
|
#undef _IF_PERIOD_RETURN_SUFFIX_ELSE
|
However, WG21-N4868 27.5.11 [time.duration.io]/1 doesn't limit charT to being only char and wchar_t. Instead, it depicts narrow string literals being directly streamed into the basic_ostream regardless of its charT (which works because const char * is always streamable, albeit with reduced performance if the types differ).
Retaining the wchar_t logic is permitted and improves performance, so we just need to fix this for other character types (like char8_t, char16_t, and char32_t).
Matt Stephanson (@MattStephanson)'s first suggested strategy in #1341 (comment) sounds good:
I think I can just switch the order of the if/else to make char the fallback, then use a conditional to get the correct return type.
We should also add test coverage for this - it doesn't have to be exhaustive, just testing a literal and a general suffix for another character type would be sufficient.
When #1341 implemented
operator<<(basic_ostream&, const duration&), its unit suffix logic handled onlycharandwchar_t:STL/stl/inc/chrono
Lines 625 to 662 in 6458199
However, WG21-N4868 27.5.11 [time.duration.io]/1 doesn't limit
charTto being onlycharandwchar_t. Instead, it depicts narrow string literals being directly streamed into thebasic_ostreamregardless of itscharT(which works becauseconst char *is always streamable, albeit with reduced performance if the types differ).Retaining the
wchar_tlogic is permitted and improves performance, so we just need to fix this for other character types (likechar8_t,char16_t, andchar32_t).Matt Stephanson (@MattStephanson)'s first suggested strategy in #1341 (comment) sounds good:
We should also add test coverage for this - it doesn't have to be exhaustive, just testing a literal and a general suffix for another character type would be sufficient.