pointer functions examples change c++ c++11 const function-pointers

change - pointers to functions in c++ examples



¿Puede una “const T*” hacer coincidir un puntero con la función libre? (1)

Si lo comprendo correctamente, esto significa que no existe una función const que no sea miembro. (Aunque tales funciones no son constantes, no pueden modificarse según 3.10 / 6). En particular, los punteros a la función const no tienen sentido.

Sí, no existe tal cosa como una función const , y los intentos de crear una se ignoran , debido al mismo párrafo que citó. Esto es importante, porque un programa que de todos modos crea un tipo de función const no está mal formado ( como fue el caso en C ++ 03 ); simplemente, su intento no se tiene en cuenta, y en su lugar se considera un tipo de función no const .

Esto es probablemente lo que GCC e ICC no aplican, porque cuando se elimina la sobrecarga no const , el programa no compila :

#include <iostream> void f() {} template <typename T> void g( T const*) { std::cout << "const " << std::endl; } int main() { g(f); // ERROR with GCC and ICC, compiles with Clang }

En cuanto a su interpretación:

Cuando se compila con GCC e Intel, el código produce "non const" como lo esperaría de la cita anterior. Sin embargo, la salida es "const" cuando se compila con Clang y Visual Studio. ¿Es mi interpretación correcta?

No lo creo Por lo que puedo decir, Clang tiene razón.

Esta conclusión se basa en el hecho de que ambas plantillas de función son viables, porque los calificadores const se ignoran en los tipos de función y uno es más especializado que el otro.

Según el párrafo 8.3.5 / 7 de la norma C ++ 11, de hecho:

[...] El efecto de un cv-qualifier-seq en un declarador de funciones no es lo mismo que agregar un cv-qualification encima del tipo de función. En este último caso, los calificadores cv son ignorados . [...]

Esto efectivamente hace que la segunda plantilla de función sea viable para resolver la llamada (la primera obviamente es). Pero como ambas plantillas de función son viables, el Párrafo 13.3.3.1 sobre la resolución de sobrecarga entra en juego:

Dadas estas definiciones, una función viable F1 se define como una función mejor que otra función viable F2 si, para todos los argumentos i, ICSi (F1) no es una secuencia de conversión peor que ICSi (F2), y luego

- para algunos argumentos j, ICSj (F1) es una mejor secuencia de conversión que ICSj (F2), o, si no es eso,

- el contexto es una inicialización por conversión definida por el usuario (ver 8.5, 13.3.1.5 y 13.3.1.6) y la secuencia de conversión estándar del tipo de retorno de F1 al tipo de destino (es decir, el tipo de la entidad que se está inicializando) es una mejor secuencia de conversión que la secuencia de conversión estándar del tipo de retorno de F2 al tipo de destino. [...] o, si no eso,

- F1 es una función no de plantilla y F2 es una especialización de plantilla de función o, si no es eso,

- F1 y F2 son especializaciones de plantilla de función, y la plantilla de función para F1 es más especializada que la plantilla para F2 de acuerdo con las reglas de ordenamiento parcial descritas en 14.5.6.2.

Como la segunda plantilla de función es más especializada que la primera, la segunda plantilla de función debe seleccionarse por resolución de sobrecarga. Por lo tanto, Clang tiene razón .

En una pregunta relacionada, se dice que no existe tal cosa como un puntero a la función const no miembro. Además, C ++ 11 8.3.5 / 6 dice

El efecto de un cv-qualifier-seq en un declarador de funciones no es lo mismo que agregar un cv-qualification en la parte superior del tipo de función. En este último caso, los calificadores cv son ignorados. [Nota: un tipo de función que tiene un cv-qualifier-seq no es un tipo calificado por cv; No hay tipos de funciones calificadas por CV . "Nota final"

Si lo comprendo correctamente, esto significa que no existe una función const que no sea miembro. (Aunque tales funciones no son constantes, no pueden modificarse según 3.10 / 6). En particular, los punteros a la función const no tienen sentido.

Sin embargo, parece que algunos compiladores crean punteros para la función const en contextos de deducción de tipo. Por ejemplo, considere el código:

#include <iostream> void f() {} template <typename T> void g( T*) { std::cout << "non const" << std::endl; } template <typename T> void g(const T*) { std::cout << "const " << std::endl; } int main() { g(f); }

Cuando se compila con GCC e Intel, el código produce "non const" como lo esperaría de la cita anterior. Sin embargo, la salida es "const" cuando se compila con Clang y Visual Studio.

¿Es mi interpretación correcta?

Actualizar:

Después de los comentarios, trato de aclarar que no estoy hablando de las funciones de miembros const. Me interesan las funciones que no son miembros (pero los mismos argumentos probablemente se apliquen también a las funciones miembros no estáticas). También he cambiado el título de la pregunta para hacerlo más preciso.

De acuerdo con la resolución de g(f) mencionada anteriormente, la siguiente línea es ilegal para GCC e Intel, pero no para Clang y Visual Studio

const auto* ptr = &f;

Actualización 2:

Estoy de acuerdo con la interpretación de Andy Prowl y he seleccionado su respuesta. Sin embargo, después de eso, me informaron que esta pregunta es un problema abierto de CWG.