Cuando un compilador puede deducir un parámetro de plantilla?

A veces funciona a veces no:

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 todo el ejemplo anterior? I. e. forzar al compilador a inferir el parámetro de plantilla de parámetro del constructor.

¿Será fijada en el futuro, o es que hay una buena razón para no hacerlo?

Lo que es la regla general, cuando el compilador puede deducir los parámetros de una plantilla?

InformationsquelleAutor | 2009-04-28

3 Kommentare

  1. 56

    Los parámetros de la plantilla se puede deducir por función de las plantillas de cuando el tipo de parámetro que se puede deducir de los parámetros de la plantilla

    Por lo que se puede deducir de 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.

    Por lo que la costumbre solución a su problema es crear una función de contenedor, de forma similar a la función de la biblioteca estándar de 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, a continuación, llamar a auto a = MakeMyClass(5); para crear instancias de la clase.

    • +1, exhaustivo. Menor nit: sugiero cambiar «cuando el tipo de parámetro es dependiente de la» a «cuando un tipo de parámetro es dependiente».
    • void f(typename T::const_iterator t); << aquí, T aparece en un undeducible contexto. incluso cuando se llama con un vector<int>::const_iterator, por ejemplo, no ser capaz de deducir vector<int> para T. la razón es que el significado de ::const_iterator depende de T. pero de nuevo depende del significado de ::const_iterator. por eso boost::implicit_cast es codificado como este: plantilla<typename T> T implicit_cast(typename identidad<T>::tipo t) { return t; } aquí de nuevo, tenemos una undeducible contexto.
    • Estándar-ref es 14.8.2.4/4 (última c++1x proyecto aún se encuentra en 14.9.2.5/5 – fijación también algunas de las deficiencias de la redacción en la norma actual). 🙂 saludos
    • Duh, tienes razón, por supuesto. No sé lo que estaba pensando.
    • Esta respuesta necesita una actualización, ya que C++17 ha introducido algunas nuevas características para argumento de plantilla de la deducción.
  2. 0

    En C++17, es posible inferir algunos tipos de uso de auto, a pesar de que los parámetros de la plantilla todavía necesitan ser especificados aquí:

    #include <iostream> 
    #include <string>
    
    template <class T1,class T2>   
    auto print_stuff(T1 x, T2 y) 
    { 
        std::cout << x << std::endl;
        std::cout << y << std::endl;
    }
    
    int main() 
    { 
        print_stuff(3,"Hello!");
        print_stuff("Hello!",4);
        return 0; 
    }

    El uso de la -fconcepts bandera en el gcc, es posible inferir los parámetros, aunque esto aún no es una parte del estándar de C++:

    #include <iostream> 
    #include <string>
    
    auto print_stuff(auto x, auto y) 
    { 
        std::cout << x << std::endl;
        std::cout << y << std::endl;
    }
    
    int main() 
    { 
        print_stuff(3,"Hello!");
        print_stuff("Hello!",4);
        return 0; 
    }

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea