2012-04-05 11 views
12

Si sobrecarga una función y luego se lo llama con un argumento que se adapta perfectamente a una de las sobrecargasNormas de conversión implícita de argumentos de plantilla

int f(int){return 3;} 
int f(bool){return 4;} 
...  //inside main() 
f(1);  //Calls f(int) 

el compilador simplemente elige este partido (perfecto) antes de intentar cualquier conversiones implícitas . Sin embargo, yo he estado tratando de sobrecargar una plantilla de función que en

template <bool veracity> 
int f(){return 1;} 

template <int amount> 
int f(){return 2;} 

...  //inside main() 
f<1>(); 

pero el compilador se mantenga complainning sobre la llamada ambigua a la sobrecarga f(), indicando que podría ser f<true>() o f<1>(). ¿No debería el compilador simplemente elegir la combinación perfecta, en lugar de tratar de convertir en true?

Tenía la impresión de que la conversión implícita para los argumentos de la plantilla era en realidad más restrictiva que la conversión implícita de los argumentos de la función. ¿Hay alguna forma de evitar este problema?

Respuesta

8

El argumento que está suministrando no es un tipo, es un valor, por lo que las reglas son un poco diferentes; debe aplicar las reglas para los argumentos que no son de tipo. Para argumentos sin tipo, se permiten conversiones implícitas. §14.3.2/5:

Las siguientes conversiones se realizan en cada expresión utilizada como argumento de plantilla sin tipo. Si un argumento de plantilla sin tipo no se puede convertir al tipo del parámetro de plantilla correspondiente, entonces el programa está mal formado.

- Para un parámetro de plantilla sin tipo de tipo integral o de enumeración, se aplican las conversiones permitidas en una expresión de constante convertida (5.19).

En C++ 03, el texto es marginalmente diferente, pero el efecto esencialmente idénticas (también §14.3.2/5):

- para una plantilla-parámetro no tipo de integral o tipo de enumeración, promociones integrales (4.5) y conversiones integrales (4.7) son aplicadas.

De cualquier manera, ya que es a la vez un 1int y convertir implícitamente a un bool, su llamada es ambigua.

+0

veo. ¿Sabes si hay una razón específica por la cual las reglas son así? Quiero decir, ¿hay alguna dificultad técnica o algo que haría que los compiladores no puedan aplicar la lógica "coincidencia exacta-primer/segundo-conversión implícita" (usada en argumentos de función) a argumentos de plantilla? – Malabarba

+0

No, no estoy seguro. Supongo que se debe principalmente a que las reglas ya son complejas, y agregar un conjunto de reglas para "clasificar" como lo hace para la sobrecarga las haría aún más. No estoy seguro, pero creo que debido a la interacción con las otras reglas para las plantillas, las reglas de clasificación terminarían al menos un poco diferentes de las de sobrecarga, así que no sería solo una cuestión de decir "las funciones candidatas formarán un conjunto de sobrecarga que se resolverá de acuerdo con §13.3". –

+0

Tiene sentido.Gracias. =) – Malabarba

5

Dado que no se trata de un error del compilador, sino de una característica de idioma (consulte this answer), tiene que encontrar una solución alternativa.

O se tiene que cambiar el nombre de sus funciones o puede utilizar este truco:

template <typename T> struct F; 

template<> struct F<bool> { 
    template <bool veracity> 
    static int f(){return 1;} 
}; 

template<> struct F<int> { 
    template <int amount> 
    static int f(){return 2;} 
}; 

template <typename T, T value> 
int f() { return F<T>::template f<value>(); } 

// inside main(): 
std::cout << f<int, 2>() << '\n'; // prints 2 
std::cout << f<bool, 2>() << '\n'; // prints 1 
Cuestiones relacionadas