2012-04-25 24 views
5

No puedo entender por qué el siguiente código compila bien:C++ instantiaion plantilla de función con los parámetros implícitos

#include <iostream>                 

void bar(int x) {                 
    std::cout << "int " << x << std::endl;            
}                     

void bar(double x) {                 
    std::cout << "double " << x << std::endl;           
}                     

template <typename A, typename B> // Note the order of A and B.            
void foo(B x) {                  
    bar((A)x);                   
}                     

int main() {                   
    int x = 1;                   
    double y = 2;                  

    foo<int>(x);  // Compiles OK.                
    foo<double>(y);  // Compiles OK.            

    return 0;                   
} 

Pero si cambio el orden de A y B como abajo, entonces no va a compilar:

#include <iostream>                 

void bar(int x) {                 
    std::cout << "int " << x << std::endl;            
}                     

void bar(double x) {                 
    std::cout << "double " << x << std::endl;           
}                     

template <typename B, typename A> // Order of A and B are switched. 
void foo(B x) {                  
    bar((A)x);                   
}                     

int main() {                   
    int x = 1;                   
    double y = 2;                  

    foo<int>(x);  // error: no matching function for call to ‘foo(int&)’ 
    foo<double>(y);  // error: no matching function for call to ‘foo(double&)’                

    return 0;                   
}  

EDIT: explicaciones ad-hoc son bienvenidos, pero sería mejor si alguien puede señalar exactamente lo que la especificación. dice. ¡Gracias!

+1

El compilador puede inferir el tipo de B en su primer ejemplo del parámetro pasado al constructor foo (de tipo B). En el segundo ejemplo, no se puede hacer tal inferencia, porque el parámetro de plantilla proporcionado es B, y también lo es el parámetro constructor. El tipo de A no está en evidencia. – Stabledog

Respuesta

7

En la primera, el compilador sabe que es Aint, ya que específicamente dice que por lo que con foo<int>, y se sabe que es B también int debido al parámetro que se le pasa. Por lo tanto A y B son conocidos o se pueden deducir (que se podría decir: A es suministrada , B es implícito).

Sin embargo, en la segunda, ya que es lo primero y BA no aparece en la lista de parámetros, el compilador no puede decir lo que es A y le da un error. Le está diciendo explícitamente qué es B con foo<int>, y luego el parámetro que pasa también es B que, en la llamada, es int que coincide con su definición explícita anterior de B, pero no se menciona A, implícitamente o explícitamente, por lo que el compilador debe detenerse y producirse un error.

Realmente no necesita el estándar para esto, es solo sentido común. ¿Qué demonios sería A en el segundo?

Gracias por hacer esta pregunta, porque no me di cuenta de que podría especificar explícitamente algunos parámetros y especificar implícitamente otros en la lista de parámetros antes de esto.

+0

Por lo tanto, esto se convierte en una cuestión de lo que la especificación. dice sobre cómo se determinan 'A' y 'B'. El compilador podría haber determinado 'B' por el argumento de entrada primero, y luego deducir' A' de 'foo '. Entonces, ambos parámetros de plantilla se determinan incluso en el segundo caso. – kirakun

+1

@Kirakun no realmente. 'A' y' B' solo se pueden determinar si especifica un tipo en '<>', o todos los que no están especificados en '<>' están en la lista de parámetros, por lo que el compilador puede deducir el escriba desde la llamada. En el segundo, 'A' no se especifica explícitamente en' <> 'ni está en la lista de parámetros, por lo que no se puede conocer. –

+1

@Kirakun solo porque pones uno en la lista de parámetros no significa que se omita cuando comienzas a poner cosas entre '<>'. Todavía están en el orden en que están en la lista 'template ', por lo que 'B' es primero, y luego' A' segundo, siempre, independientemente de los argumentos que tome la función. –

Cuestiones relacionadas