简体   繁体   中英

operator++ as both a postfix and prefix doesn't work with clang

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM