I tried to write an operator that can be used both as a prefix and a postfix operator
#include <iostream> #include <utility> struct B { // ... }; template<typename ...T> void operator++(B, T...) { std::cout << ((sizeof...(T) == 0) ? "prefix" : "postfix") << std::endl; } int main() { B b; b++; ++b; }
GCC compiles and works fine with this, but clang says
main.cpp:9:24: error: parameter of overloaded post-increment operator must have type 'int' (not 'T...')
void operator++(B, T...) {
Who is right?
Thanks to anyone who helped me understand GCC's behavior. I filed a new Clang bug report:
http://llvm.org/bugs/show_bug.cgi?id=14995
Increment ++ and Decrement -- Operator as Prefix and Postfix In programming (Java, C, C++, JavaScript etc.), the increment operator ++ increases the value of a variable by 1. Similarly, the decrement operator -- decreases the value of a variable by 1. Simple enough till now.
++i++ is an error by the current definition of C. The language could easily be changed to have an explicit rule for this expression (produce the value ((i+=2),i-1) ), but given how often it would be used, it's hardly worth the effort.
The main difference between prefix and postfix is that the prefix is a notation that writes the operator before operands while the postfix is a notation that writes the operator after the operands.
To distinguish between the two, the following rule is observed: The prefix form of the operator is declared exactly the same way as any other unary operator; the postfix form accepts an extra argument of type int .
ORIGINAL ANSWER: (not deleted as it may contain useful information)
I would say it all boils down to whether an overloaded operator template is considered to be an overloaded operator or not. Logically, I would like to think this is not the case, and Clang is wrong: I believe the template should be first selected as a candidate for overload resolution based on name and signature compatibility, then instantiated, then (possibly) selected. The way I see it, only after instantiation the compiler should check whether the resulting function has the proper amount of arguments or not.
But that is only my opinion. Per § 13.5.7/1 about overloading of the postfix operator ++
:
"If the function is a member function with one parameter (which shall be of type int) or a non-member function with two parameters (the second of which shall be of type int), it defines the postfix increment operator ++ for objects of that type"
The Standard does not seem to clarify whether a function template shall be considered as a function for what concerns the restrictions on the signature of legal operator overloads (at least, I could not find any sentence that solves this ambiguity). As long as this is true, this question can hardly be given a clear answer, and we are left with opinions.
But I would like to mention another relevant aspect of the matter: consistency.
Although it is true that the code in the question's text does not compile on Clang, the following does:
template<typename... Ts> int operator + (X x1, Ts... args) { return 0; }
I do not see any conceptual difference between the two cases: if the signature of the operator overload is to be checked before instantiation, then the above definition should not compile either. If this is not the case, then the code in the question's text should compile.
So the answer in my opinion is that either GCC is right, or they are both wrong.
UPDATE:
As @JesseGood and @SethCarnegie correctly point out, per 14.7/4:
"A specialization is a class, function, or class member that is either instantiated or explicitly specialized."
Moreover, per 14.6/8:
"No diagnostic shall be issued for a template for which a valid specialization can be generated."
Thus, it seems Clang is indeed wrong and no compilation error shall be produced for the operator function template in the question's text.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With