2011-07-08 9 views
9

El impulso :: función FAQ item 3 aborda específicamente el escenario Estoy interesado en:¿Puede tr1 :: funcionar tragar los valores devueltos?

¿Por qué hay soluciones para huecos retornos? C++ les permite! regresa vacía son permitidos por la norma de C++, como en este fragmento de código:

void f(); 
void g() { return f(); } 

Este es un uso válido de impulso :: función porque los retornos vacíos no se utilizan. Con retornos de vacío, que sería intentar compilar mal formada código similar a:

int f(); 
void g() { return f(); } 

En esencia, no usar void Devuelve permite impulso :: función de tragar un valor retorno. Esto es coherente con que permite al usuario asignar e invocar a las funciones y objetos de función con los parámetros que no coinciden exactamente.

Por desgracia, esto no funciona en VS2008:

int Foo(); 
std::tr1::function<void()> Bar = Foo; 

Esto produce errores a partir de:

c:\Program Files\Microsoft Visual Studio 9.0\VC\include\xxcallfun(7) : error C2562: 'std::tr1::_Callable_fun<_Ty>::_ApplyX' : 'void' function returning a value 

Es éste un defecto de la aplicación VS2008 TR1? Funciona esto en VS2010? ¿TR1 aborda esta capacidad? ¿Qué hay de C++ 0x?

+0

VS2010 da el mismo error. – Xeo

+2

'void g() {return f(); } 'está permitido admitir código de plantilla donde el tipo de retorno de la función podría no conocerse de antemano ... aún es un error para' f() 'devolver realmente un valor si' g() 'no lo hace. Ante esto, no me sorprendería encontrar que el comité de estándares eligió divergir de la implementación de Boost en este aspecto, ya que proporciona un comportamiento más intuitivo. Pero como gcc * does * permite este comportamiento, no soy positivo. –

Respuesta

8

Creo que tr1 resuelve este problema. N1836 (el último borrador TR1) dice:

Un objeto de la función f de tipo F es Callable para tipos de argumentos T1, T2, ..., TN y un tipo de retorno R, si, dada lvalues ​​t1 , t2, ..., tNoftypesT1, T2, ..., TN, respectivamente, INVOKE (f, t1, t2, ..., tN) está bien formado ([3.3]) y, si R es no vacío, convertible en R.

En su ejemplo R es nulo, y por lo que la última parte de los requisitos para Callable (convertible a R) es ignorar re.

Sin embargo, parece que C++ 0x (C++ 11) cambia las reglas. En C++ 11 Callable se define como INVOKE(f, t1, t2, ..., tN, R) que se define en [func.require] como requiriendo que INVOKE(f, t1, t2, ..., tN) sea implícitamente convertible a R, sin excepción para cuando R es nulo. Entonces, en C++ 11, tu ejemplo debería fallar.

+2

¿Sabes si existe una razón fundamental para este cambio/regresión? Si no, suena como un defecto. –

+0

Esto de hecho suena raro. Ninguna expresión es implícitamente convertible a 'void'.Ni siquiera una expresión de tipo 'void' (según la cláusula 4, párrafo 3). Uno necesita un molde explícito para convertir cosas a 'void'. Supongo que la intención es que solo si el tipo de resultado es diferente de 'R ', entonces la expresión se convierte implícitamente en' R'. Entonces el resultado aún podría tener el tipo 'void' cuando' R' es 'void'. Sin embargo, es fácil ser engañado por esos párrafos, IMO :) –

Cuestiones relacionadas