Creo que se puede confundir entre los valores de r y el calificador const. function
devuelve un rvalue no const temporal de tipo int, por lo que el compilador deduce que T sea int, como debería ser. Como usted señala, puede enlazar un temporal a una ref constante (C++ 03 12.2/5), pero el compilador no agregará calificadores cv para hacer una llamada a función bien formada. Como no puede controlar la función de plantilla, hay dos formas de evitar esto (además de la solución que publicó).
(1) explícitos parámetros de plantilla: function2<const int>(function())
(2) cv calificar retorno: const int function();
Ambas soluciones están bien formadas. (1) parece la mejor solución, en mi humilde opinión, ya que (2) es poco convencional y tonto.
Editar: En realidad, el tipo deducido puede ser más cv-calificado que el argumento para un argumento de plantilla ref, pero solo si la deducción de tipo de lo contrario no (C++ 03 14.8.2.1/3). En este caso, la deducción del tipo no falla, pero da como resultado una llamada de función mal formada (SFINAE no se aplica, porque la especialización de la función de la plantilla no está mal formada).
Si la intención del autor de la plantilla era no modificar el argumento, debe declararse como un argumento de referencia constante, por lo que puede tratarse de un error en la biblioteca de plantillas o modificar el argumento, en cuyo caso lo que está haciendo fallará cuando la función intente modificar el argumento.
Editar: Como FredOverflow señala, los valores de clase no siempre son cv no calificados por el estándar 3.10/9. Entonces (2), que funciona bajo gcc 4.3, es en realidad un error de compilación (gcc < 4.5, según FredOverflow).
@aca Para ser más precisos, [los valores r no pertenecientes a la clase siempre tienen tipos cv no calificados] (http: // stackoverflow.com/questions/2169932/non-class-rvalues-always-have-cv-un-kalified-types) ;-) Para class-types, hay una distinción entre rvalues modificables y valores de configuración, por lo que, en general, el 'const' es * no * superfluo! Puede llamar a métodos no const en valores r modificables y así cambiar los objetos subyacentes. Por ejemplo, 'std :: string (" hello ") .append (" world! ")'. – fredoverflow
@FredOverflow sí, buen punto. Observe que los valores de matriz se califican de la misma manera (el Estándar dice que no lo son, pero no son los menos; no puede escribir 'struct A {const int a [1];}; .. A(). A [0] = 0;' en la mayoría de los compiladores (excepto en Comeau, donde puede), pero si elimina el 'const', puede (ha habido preguntas en usenet y en otros lugares sobre esto, aún no se ha encontrado una solución). También observe que cualquier no- class/type/rvalue no es un objeto. Class-type/array-type rvalues son objetos, por lo tanto const tiene sentido para ellos (ver nota al pie en 4.1/1 en el estándar). –
@FredOverflow me pregunto qué @aca comentó que usted respondió? ¿Eliminó su comentario? –