2012-08-29 10 views
12

¿Se tratan los objetos de funciones de forma diferente a las funciones normales durante la resolución de sobrecarga? ¿Si es así, cómo?¿Cómo afectan los objetos a la resolución de sobrecarga?

he ejecutar en el siguiente caso en el que la sustitución de una función con un objeto de función equivalente-exigible cambió el significado del código:

#include <iostream> 

namespace N 
{ 
    enum E { A, B }; 

    void bar(E mode) { std::cout << "N::bar\n"; } 
} 

template <typename... Args> 
void bar(Args&&... args) { std::cout << "global bar\n"; } 

int main() 
{ 
    bar(N::A); 
} 

Aquí la salida es "N :: bar". Hasta ahora, todo bien: ND bar está siendo encontrado por ADL, tanto N :: bar como la barra global son coincidencias exactas, y se prefiere N :: bar porque no es una plantilla.

Pero si cambio de la barra global para ser un objeto de función, así:

#include <iostream> 

namespace N 
{ 
    enum E { A, B }; 

    void bar(E mode) { std::cout << "N::bar\n"; } 
} 

struct S 
{ 
    template <typename... Args> 
    void operator()(Args&&... args) { std::cout << "global bar\n"; } 
}; 
S bar; 

int main() 
{ 
    bar(N::A); 
} 

La salida es ahora "global bar". ¿Por qué la diferencia?

Respuesta

12

Lo importante aquí es que ADL solo se activa si la búsqueda determina que el nombre es una función en la llamada a la función. En el segundo caso, bar es un objeto y no una función, por lo que la expresión bar(N::A) no es una llamada a función, sino la aplicación de operator() al objeto bar. Como no es una llamada de función, ADL no se activa y no se considera N::bar.

3.4.1/3

La búsqueda para un nombre no calificado utilizado como el postfix-expresión de una llamada de función se describe en 3.4.2. [Nota: a los efectos de determinar (durante el análisis sintáctico) si una expresión es una expresión de postfijo para una llamada de función, se aplican las reglas habituales de búsqueda de nombre. Las reglas en 3.4.2 [ADL] no tienen ningún efecto en la interpretación sintáctica de una expresión.

Otra forma de verlo es darse cuenta de que ADL añadirá nuevas funciones a la conjunto de funciones sobrecargadas, pero en el segundo ejemplo no existe tal conjunto: operaciones de búsqueda encuentra un objeto y un miembro de la objeto se llama.

+2

Hoy aprendí, gracias David. – ildjarn

+0

No creo que la nota en 3.4.1/3 es relevante, porque 'bar' * es * la expresión de postfijo en una expresión de llamada a función (¡que no tiene una función como operando, pero finalmente llama a uno!). La nota dice que 3.4.2 no cambia el significado sintáctico de "x (y)" - si se trata de una llamada a función, se mantiene como una llamada de función sin tener en cuenta lo que 3.4.2 decide hacer. –

+0

@ JohannesSchaub-litb: la búsqueda regular encontrará que 'bar' es un objeto, y al ser un objeto' bar (x) 'representa la aplicación de' operator() 'a esa instancia. Mientras que la aplicación del operador es una llamada a función, es una llamada a * member-function * y, por lo tanto, ADL no se aplica. –

4

Ver 3.4.2p3, que dice

Sea X el conjunto de las operaciones de búsqueda producido por las operaciones de búsqueda no calificado (3.4.1) y Sea Y el conjunto de las operaciones de búsqueda producido por las operaciones de búsqueda depende argumento (que se define como sigue). Si X contiene

  • ...
  • una declaración de que no es ni una función o una plantilla de función

entonces Y es vacío.

Si no hubiera tal regla, tiene razón: ADL agregaría su otra función al conjunto de sobrecarga. De hecho, 13.3.1.1p1 se basa en esto: tiene dos ramas; uno para las expresiones de llamadas de funciones donde el operando denota un objeto de clase, y otro donde el operando denota una o más funciones o plantillas de funciones.

+0

+1, después de revisar esa parte de la norma, la cita que proporcionó es el motivo de la nota que cité. –

+0

@david lo estás malinterpretando –

Cuestiones relacionadas