Not variadic expression templates
At the Kona committee meeting, it was voted (by someone, probably LEWG, I forget the story,
I wasn’t in the room) to eliminate the overloaded operator() from C++2a std::span.
Now it has only operator[].
The overloaded operator() was there merely for consistency with std::mdspan,
which isn’t slated for C++2a.
std::mdspan needed an overloaded operator() because it couldn’t use overloaded operator[]
because operator[] is a purely binary operator: s[a] means s.operator[](a), but
s[a,b] means s.operator[]((a,b)) which means the same thing as s.operator[](b) because
that’s what the comma operator does.
According to the minutes of the Kona meeting (again I wasn’t in the room), Corentin Jabot’s P1161R2 “Deprecate uses of the comma operator in subscripting expressions” (October 2018) was forwarded to CWG for inclusion in C++2a. This is great news!
Because the next thing that could happen, after a period of deprecation, is that C++2b might
finally allow multi-argument operator[] overloads, the same way C++98 allowed multi-argument
operator() overloads. Then mdspan (which is slated for C++2b) could use a multi-argument
operator[]: you could index a single span as s[a] and a multi-dimensional mdspan as s[a,b].
(Of course then we’d really have to argue about whether C++ has multidimensional arrays or
just single-dimensional arrays of arrays. I think the right answer is the latter. But anyway…)
Talking about multi-argument operator overloads over breakfast made me think up the following code snippet.
#include <type_traits>
struct A {
int value = 0;
A(int v): value(v) {}
template<class... Ts,
class = std::enable_if_t<(std::is_same_v<Ts, A> && ...)>>
A operator+(Ts... ts) {
return A((this->value + ... + ts.value));
}
};
A a = 1;
A b = a;
A c = a + b;
A d = a + b + c;
A e = a + b + c + d;
Here I’ve given A a variadic overloaded operator+ that accepts any number of A objects
and adds them together using a C++17 fold-expression. And Clang is totally happy with this code.
But if your coworker wrote this code, hoping for some expression-templatey kind of thing,
they’d be sadly mistaken! This example might make clearer what’s
going on: we have here an operator+ that can accept a variadic number of parameters, but the
compiler will never give it more than the usual two at a time. All we’ve done by making it
variadic is we’ve permitted the same operator to be called as both a binary operator (a+b)
and a unary operator (+a). There’s no such thing in C++ as a “ternary operator +”!
See also: the prefix-or-postfix-I-don’t-care increment operator.
