2009-04-28 18 views
27

veces, a veces no funciona:¿Cuándo un compilador puede inferir un parámetro de plantilla?

template <class T> 
void f(T t) {} 

template <class T> 
class MyClass { 
public: 
    MyClass(T t) {} 
}; 

void test() { 
    f<int>(5); 
    MyClass<int> mc(5); 
    f(5); 
    MyClass mc(5); // this doesn't work 
} 

¿Hay una manera de cortar alrededor del ejemplo anterior? Es decir. obligar al compilador a deducir el parámetro de plantilla del parámetro constructor.

¿Esto se solucionará en el futuro, o hay una buena razón para no hacerlo?

¿Cuál es la regla general cuando el compilador puede inferir un parámetro de plantilla?

Respuesta

47

parámetros de plantilla pueden ser inferidas de plantillas de función cuando el tipo de parámetro se puede deducir de la plantilla parámetros

Por lo tanto, se puede inferir aquí:

template <typename T> 
void f(T t); 

template <typename T> 
void f(std::vector<T> v); 

pero no aquí:

template <typename T> 
T f() { 
    return T(); 
} 

Y no en plantillas de clase.

Así que la solución a su problema habitual es crear una función de contenedor, similar a la función de la biblioteca estándar std::make_pair:

template <class T> 
    class MyClass { 
    public: 
     MyClass(T t) {} 
     void print(){ 
      std::cout<<"try MyClass"<<std::endl; 
     } 
    }; 

    template <typename T> 
    MyClass<T> MakeMyClass(T t) { return MyClass<T>(t); } 

y luego llamar auto a = MakeMyClass(5); para crear instancias de la clase.

+0

+1, a fondo. Minor nit: sugiero cambiar "cuando el tipo de parámetro es dependiente" a "cuando un tipo de parámetro es dependiente". –

+2

void f (nombre de tipo T :: const_iterator t); << aquí, T aparece en un contexto no deducible. incluso cuando lo llame con un vector :: const_iterator, por ejemplo, no podrá deducir el vector para T. la razón es que el significado de :: const_iterator depende de T. pero T depende de nuevo del significado de :: const_iterator. es por eso que boost :: implicit_cast está codificado así: plantilla T implicit_cast (typename identity :: type t) {return t; } aquí de nuevo, tenemos un contexto no deducible. –

+0

Standard-ref es 14.8.2.4/4 (el último borrador de C++ 1x lo tiene ubicado en 14.9.2.5/5 - arreglando también algunas de las deficiencias de la redacción en el estándar actual). :) aplausos –

Cuestiones relacionadas