2010-03-11 17 views
11

tengo este código:Visual Studio 2010 y std :: función

#include <iostream> 
#include <functional> 

struct A 
{ 
    int operator()(int i) const { 
     std::cout << "F: " << i << std::endl; 
     return i + 1; 
    } 
}; 

int main() 
{ 
    A a; 
    std::tr1::function<int(int)> f = std::tr1::ref(a); 
    std::cout << f(6) << std::endl; 
} 

El objetivo es pasar el objeto por un funtor reference_wrapper, en una forma de evitar las llamadas copia costructor inútiles. espero que el siguiente resultado:

F: 6 
7 

Funciona correctamente con GCC> = 4.4.0, Visual Studio 2008 y con el impulso mediante la sustitución de espacio de nombres std :: TR1 con impulso. Solo no funciona con el nuevo Visual Studio 2010 tanto Express Beta 2 como Release Candidate.

¿Están estas nuevas características de C++ ocultas en vs2010? O hay algún error o mal uso en el código?

+0

¿Cómo no funciona? – UncleBens

+0

@litb: Creo que el OP tiene problemas con el uso de la clase de plantilla 'std :: tr1 :: ref' y * not * boost en VS2010. – dirkgently

+0

Aquí es el resultado de generación de VS2010: http://pastebin.com/YQf4Qe8W –

Respuesta

11

Creo que encontré el motivo. Esto es lo que TR1 3.4/2 dice acerca de result_of<T(A1, A2, ..., AN)>::type, utilizado en la determinación del tipo de retorno de reference_wrapper<T>::operator():

La implementación puede determinar el miembro de tipo a través de cualquier medio que produzca el tipo exacto de la expresión f (t1, t2, ..., tN) para los tipos dados. [Nota: La intención es que las implementaciones están autorizados a utilizar ganchos especiales del compilador -END nota]

Y luego el párrafo 3:

Si F no es un objeto de la función definida por la biblioteca estándar, y si la implementación no puede determinar el tipo de la expresión f (t1, t2, ..., tN) o si la expresión está mal formada, la implementación debe usar el siguiente proceso para determinar el miembro tipo:

  • Si F es un tipo de clase posiblemente cv-calificado sin memb er llamado result_type o si typename F::result_type no es un tipo:
    • Si N = 0 (sin argumentos), el tipo es nulo.
    • Si N> 0, el tipo es typename F::template result<F(T1, T2,..., TN)>::type

El mensaje de error es un artefacto de tratar estos otoño-backs. Proporcione un typedef para result_type a int y debería funcionar, creo. Tenga en cuenta que en C++0x, esto es diferente. No se basa en result_type o en una plantilla result, ya que puede usar decltype.

Si con <functional> falla con MSVC10 en modo C++ 0x, diría que huele a error. Pero tal vez alguien más sepa lo que está pasando. Puede (pero no está garantizado) trabajar con <tr1/functional> en modo C++ 0x si ese encabezado elige tomar la forma decltype en lugar de ::result_type. Me gustaría typedef result_type - de esa manera, creo que siempre debería funcionar, independientemente de si se utiliza el encabezado tr1 o el encabezado c++0x.


Observe también que boost::tr1 dice en su documentación que no admite el operador de llamada de función (pero sólo soporta conversiones implícitas a T&).

+1

Sí, esto soluciona el problema: D Es un lástima de vs2010 para esta regresión con respecto a la versión anterior de 2008 ... El borrador más reciente requiere estrictamente que el compilador pueda reconocer el tipo de devolución automáticamente. http://www.open-std.org/JTC1/SC22/ WG21/docs/papers/2009/n3000.pdf Párrafo 20.7.4 –