2011-10-14 6 views
7

La siguiente falla al compilar el compilador VC++ 8.0 con un error (no he probado en el último compilador Visual Studio todavía.)La deducción de argumentos de la plantilla falla en MSVC: ¿error?

error C2440: const no se puede convertir de': 'retorno' char *' a ' const char (&) [6]'

template <typename T> 
inline T const& compare (T const& a, T const& b) 
{ 
    return a < b ? b : a; 
} 

int main() 
{ 
    ::compare("string1", "string2"); 
} 

Dentro de la plantilla de función, parece cadenas son const char (&)[6].

Por lo que sé, cuando se aplica el operador <, la matriz debe decaer a puntero. Entonces, ¿podría este error ser debido a un posible error?

+0

gcc [compila] (http://ideone.com/WVU4h) este código sin ningún problema, por lo que este debe ser un error en MSVC. – Vlad

+1

Es poco probable que desee pasar C cadenas a dicha plantilla de todos modos (para comparar sus direcciones). – UncleBens

+0

Esto parece un error, MSVC dice el tipo de la expresión 'a Praetorian

Respuesta

3

Es ciertamente un error en el compilador de Microsoft.

Aquí hay una gran diferencia en C y C++.

e0 ? e1 : e2 

En C++, una condtional-expresión produce lvalue, menos al menos una de las expresiones de la segunda parte (después de '?') es un valor p, mientras que en C, una condicionalidad expresión siempre produce rvalue, no importa qué. Eso significa que, el siguiente código es perfectamente válido en C++, pero es un error en C:

int a=10, b=20; 
(a<b?a:b) = 100; //ok in C++, but error in C 

En C++, no se trata a un error, precisamente por la expresión (a<b?a:b) es la expresión de valor-I, así como se puede poner en el lado izquierdo de una tarea.

Volviendo ahora a la pregunta original. En su caso, a y b son matrices de tipo char (&) [6], y la expresión a<b? a : b debe producir un valor l, ya que no es necesario conversión de matriz a puntero. Pero en el compilador de Microsoft, parece que hay una conversión de matriz a puntero.

Para verificarlo, se puede escribir la siguiente:

template <typename T, int N> 
inline void f(T const (&a)[N]) {} 

template <typename T> 
inline T const& compare (T const& a, T const& b) 
{ 
    f(a < b ? b : a); //is the argument `char*` OR `char (&)[6]`? 
    return a < b ? b : a; 
} 

y da no error ya sea (en GCC), lo que significa la expresión del cual se establece f() es una matriz, no un puntero.

+0

Aunque es correcto para esta situación, su afirmación acerca de si una expresión condicional es un _valor es demasiado fuerte. Tanto la segunda como la tercera expresiones pueden ser _glvalues_, pero la expresión aún puede ser un _prvalue_ si no tienen los mismos tipos y la conversión de cualquiera de ellos dos un tipo común no produce un _glvalue_ directamente enlazado. –

+0

@CharlesBailey: Creo que lo que dijiste es cierto solo para C++ 11, y C++ 03 no tiene esos conceptos. Mi publicación es sobre C++ 03, ya que el OP está utilizando MSVS 2008 que no implementó las características de C++ 11. – Nawaz

+0

Bueno, obviamente, tiene que leer _lvalue_ para _glvalue_ y _rvalue_ para _prvalue_, pero fundamentalmente esto todavía era cierto en C++ 03. –

0

Por lo que sé, cuando se aplica el operador <, la matriz debe decaer al puntero.

Ese es el problema, es que se descomponían en una const char * pero por otra parte está tratando de convertir eso en const char [8] para el valor de retorno.

no estoy seguro de lo que la norma dice acerca de esto, pero si lo cambia a cualquiera:

compare<char *>("string1","string2"); 

o

compare(static_cast<const char *>("string1"),static_const<const char *>("string2")); 

A continuación, el parámetro de plantilla T habrá char * lugar char [8].

Cuestiones relacionadas