Skip to content

<chrono>: [time.duration.io] output should handle types beyond char and wchar_t #1430

@StephanTLavavej

Description

@StephanTLavavej

When #1341 implemented operator<<(basic_ostream&, const duration&), its unit suffix logic handled only char and wchar_t:

STL/stl/inc/chrono

Lines 625 to 662 in 6458199

#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).

@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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinginvalidThis issue is incorrect or by design

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions