c++ - una - operador decremento c
operador++ ya que tanto un postfijo como un prefijo no funcionan con clang (1)
RESPUESTA ORIGINAL: ( no eliminado ya que puede contener información útil )
Diría que todo se reduce a si una plantilla de operador sobrecargada se considera que es un operador sobrecargado o no. Lógicamente, me gustaría pensar que este no es el caso, y Clang está equivocado: creo que la plantilla debería seleccionarse primero como candidato para la resolución de sobrecarga basada en el nombre y la compatibilidad de firmas, luego crear instancias y luego (posiblemente) seleccionar. Tal como lo veo, solo después de la creación de instancias el compilador debe verificar si la función resultante tiene la cantidad adecuada de argumentos o no.
Pero esa es solo mi opinión . Según § 13.5.7 / 1 sobre la sobrecarga del operator ++
postfix operator ++
:
"Si la función es una función miembro con un parámetro (que debe ser de tipo int) o una función no miembro con dos parámetros (el segundo de los cuales será del tipo int), define el operador de incremento postfix ++ para los objetos de ese tipo "
La Norma no parece aclarar si una plantilla de función se debe considerar como una función para lo que se refiere a las restricciones sobre la firma de sobrecargas de operadores legales (al menos, no pude encontrar ninguna oración que resuelva esta ambigüedad). Mientras esto sea cierto, difícilmente se puede dar una respuesta clara a esta pregunta, y nos quedan opiniones .
Pero me gustaría mencionar otro aspecto relevante del asunto: la coherencia .
Aunque es cierto que el código en el texto de la pregunta no se compila en Clang, lo siguiente hace:
template<typename... Ts>
int operator + (X x1, Ts... args)
{
return 0;
}
No veo ninguna diferencia conceptual entre los dos casos: si la firma de la sobrecarga del operador debe verificarse antes de la creación de instancias , entonces la definición anterior tampoco debería compilarse. Si este no es el caso, entonces el código en el texto de la pregunta debe compilarse.
Entonces, la respuesta en mi opinión es que, o bien GCC tiene razón, o ambos están equivocados.
ACTUALIZAR:
Como @JesseGood y @SethCarnegie señalan correctamente, por 14.7 / 4:
"Una especialización es una clase, función o miembro de clase que está instanciado o explícitamente especializado".
Además, por 14.6 / 8:
"No se emitirá ningún diagnóstico para una plantilla para la cual se puede generar una especialización válida".
Por lo tanto, parece que Clang es incorrecto y no se producirá ningún error de compilación para la plantilla de función del operador en el texto de la pregunta.
Traté de escribir un operador que se puede usar como prefijo y como operador de postfijo
#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 compila y funciona bien con esto, pero dice clang
main.cpp: 9: 24: error: el parámetro del operador de incremento de carga sobrecargado debe tener el tipo ''int'' (no ''T ...'')
void operator++(B, T...) {
¿Quién tiene la razón?
Gracias a todos los que me ayudaron a entender el comportamiento de GCC. Archivé un nuevo informe de error de Clang: