In MSVC chrono implementation I see the following code
_EXPORT_STD template <int = 0>
_NODISCARD constexpr year_month operator+(const year_month& _Left, const months& _Right) noexcept {
const auto _Mo = static_cast<long long>(static_cast<unsigned int>(_Left.month())) + (_Right.count() - 1);
const auto _Div = (_Mo >= 0 ? _Mo : _Mo - 11) / 12;
return year_month{_Left.year() + years{_Div}, month{static_cast<unsigned int>(_Mo - _Div * 12 + 1)}};
}
Can someone explain me why it uses template with unnamed parameter ?
4
1 Answer
You have two very similar overloads for operator+
, originally without the template
template <int = 0>
constexpr year_month operator+(const year_month& _Left, const months& _Right) noexcept
constexpr year_month operator+(const year_month& _Left, const years& _Right) noexcept
It was discovered that if you have a value that is convertible to both months
and years
, there was an ambiguity here. Which conversion should be chosen?
By making one of the operators (a dummy) template, the non-template is chosen (if possible) because templates have lower priority in overload resolution.
The standard specifies this requirement a bit convoluted (backwards in my opinion):
"If the argument supplied by the caller for the months parameter is convertible to years, its implicit conversion sequence to years is worse than its implicit conversion sequence to months"
So if the conversions are equally good, the non-template is to be chosen. Only if conversion to months is better, the template gets a chance.
(And the standard doesn’t explicitly say that is has to be a template, but that is a way of implementing this requirement).
1
-
1
And the reason for the specification to be this way is because adding a multiple of
years
can be implemented slightly more efficiently than addingmonths
: Just add to the internalyear
field without touching themonth
field.– Howard Hinnant17 hours ago
Related post that possibly answers your question: stackoverflow.com/questions/59824884/…
23 hours ago
I understand that there are cases where unnamed template parameter can be useful, but I don't understand in this particular case. Why would we need specialization ? Especially with operator+ you can't even pass a template parameter when writing "ym + m"
23 hours ago
Candidate for C++ question (and answer) of the week award?
22 hours ago
I still would try to avoid writing
auto x = operator+<0>(ym, m);
17 hours ago