compile c++ templates gcc clang

c++ - compile - clang windows



Clang "no pudo inferir el argumento de la plantilla" mientras que gcc/g++ sí puede. ¿Lo cual está bien? (2)

He intentado compilar un proyecto (que está bien usando gcc / g ++) con clang y compilación bloqueados en una invocación de plantilla. Intenté crear la pieza de código similar más simple que muestre el mismo mensaje de error. Aquí está:

#include <vector> #include <utility> #include <iostream> using namespace std; int A( double in ) { return 1; } int A( int in ) { return 1; } template<class M, class T> M test(T input, M (fun) (T) ) { return fun( input ); } int main( int argc, const char *argv[] ) { cout << test( (int) 1, A ) << test( (double) 1.2, A ) << endl; return 0; }

El error de clang (aparece dos veces, por supuesto):

error: no matching function for call to ''test'' candidate template ignored: couldn''t infer template argument ''M''

Gcc no se queja. Tenga en cuenta que M es el tipo de devolución y siempre es "int".

¿Alguien sabe cuál es el correcto y por qué?

Gracias


Mi respuesta anterior (ahora eliminada) fue incorrecta. Clang está equivocado.

El compilador debería poder deducir el tipo M porque el argumento de la función es M(fun)(T) . Tenga en cuenta que no hay M en la lista de argumentos del puntero a la función, por lo que esto corresponde a la T() (C ++ 11) / T(*)() (C ++ 93) en 14.8.2.5:

donde (T) representa una lista de tipos de parámetros donde al menos un tipo de parámetro contiene una T , y () representa una lista de tipos de parámetros donde ningún tipo de parámetro contiene una T


g ++ es incorrecto. Desde C ++ 11 [temp.deduct.type] p5:

Los contextos no deducidos son: [...] - Un parámetro de función para el que no se puede hacer una deducción de argumento porque el argumento de la función asociada [...] es un conjunto de funciones sobrecargadas, [...] y más de una función coincide con el tipo de parámetro de función

Esta determinación se realiza sin tener en cuenta los parámetros de la plantilla que podrían haber sido deducidos en otro lugar, por lo que el hecho de que T debe deducir como int no es relevante aquí. Esto hace que todo el parámetro M (fun)(T) un contexto no deducido. Por lo tanto, M no se puede deducir, como afirma Clang.

g ++ parece estar usando incorrectamente la deducción '' T = int '' del primer parámetro de función al determinar si el segundo parámetro es un contexto no deducido. Invertir el orden de los parámetros de la función hace que g ++ también rechace el código:

int A(double); int A(int); template<class M, class T> M test(M (fun) (T), T input) { return fun( input ); } int main( int argc, const char *argv[]) { test(A, 1); test(A, 1.2); }