2012-10-05 14 views
8

Necesito crear un predicado a partir de la función de miembro enlazado, así que lo envolví en un boost::function<bool(SomeObject const &)>. Eso parece estar bien y todo, pero también necesitaba negarlo en un caso. Sin embargoColapso de referencia bajo C++ 03

boost::function<bool(SomeObject const &)> pred; 
std::not1(pred); 

no compila bajo MSVC++ 9.0 (Visual Studio 2008), quejándose de que consultará la referencia no es válida:

C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\functional(213) : warning C4181: qualifier applied to reference type; ignored 
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\functional(213) : error C2529: '_Left' : reference to reference is illegal 

El problema es que boost::function define el argument_type como SomeObject const & y la std::unary_negate<_Fn1> instancia por std::not1 internamente trata de usar const typename _Fn1::argument_type& y el compilador lo rechaza porque T::argument_type ya es una referencia. Estoy seguro de que eso debería compilarse bajo C++ 11, pero este es un viejo compilador que solo es C++ 03. Así que me gustaría saber quién es la culpa que es:

  • del compilador, ya que debe derrumbarse la referencia (apparently not),
  • de la biblioteca estándar, ya que debe estar preparado para manejar funtores que toman referencias (al parecer no es así, debido a que la especificación define unary_negate con const typename Predicate::argument_type& x argumento),
  • impulso de, porque no debería ser argument_type referencia incluso cuando el argumento actual es o
  • mío, porque boost::function no debe utilizarse con argumentos de referencia?
+0

¿Se compila bajo otros compiladores? – eh9

+0

@ eh9: con gcc compila, al menos para objetivos mingw32 y cygwin. –

+0

@ eh9: Pero no es demasiado relevante para la pregunta; quién es el culpable y por qué depende de la especificación. –

Respuesta

1

La falla ciertamente no es la de Boost; boost::function es básicamente std::function, con la misma semántica. Y boost::function s con parámetros de referencia también funcionan bien. Simplemente no puede usarlos con std::not1 o el resto de las cosas <functional>.

El colapso de referencia de C++ 11 hace que std::not1 funcione de la forma que usted cree que debería. La forma en que se especificó std::not1 en C++ 03 no podría funcionar sin colapso de referencia, excepto en implementaciones donde los implementadores hicieron un poco de interpretación creativa en lugar de seguir servilmente la letra del Estándar.

Es posible hacer std::not1 trabajo en C++ 03 mediante la adición de una especialización de std::unary_negate de predicados con referencia argument_type s, pero tampoco libC++ ni libstdC++ lo ha hecho.

¿Pero sabes quién? Boost! Si solo cambia el código para usar boost::not1 en todos los lugares que usa actualmente std::not1, everything will work fine. Básicamente, piense en el espacio de nombres boost como si fuera una versión compatible con C++ 11 de std; cualquier cosa que funcione en el espacio de nombres std de C++ 11 probablemente funcione en el espacio de nombres boost de C++ 03.


Advertencia, es de esperar fuera de tema: El compilador Clang en mi Macbook (Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)) se derrumba en silencio referencias incluso en el modo de -std=c++03, de manera que

typedef const int& ref; 
typedef const ref& ref2; 

produce ningún error.Cuando pruebe su código C++ 03, asegúrese de no estar utilizando un compilador con esta característica incorrecta.

Cuestiones relacionadas