2010-12-07 16 views
5

Por alguna razón, no puedo usar boost::format en un boost::lambda. Aquí está una (esperemos) la simplificación compilables de mi código:Uso de boost :: formato en un impulso :: lambda

#include <algorithm> 
#include <iomanip> 
#include <iostream> 

#include <boost/assign/list_of.hpp> 
#include <boost/format.hpp> 
#include <boost/lambda/lambda.hpp> 

namespace bl = boost::lambda; 

int main() 
{ 
    const std::vector<int> v = boost::assign::list_of(1)(2)(3); 
    std::for_each(v.begin(), v.end(), bl::var(std::cout) << std::setw(10) << bl::_1); 
    std::for_each(v.begin(), v.end(), bl::var(std::cout) << boost::format("%10d") % bl::_1); 
} 
  • La primera std::for_each produce la salida esperada
  • El segundo std::for_each única salida a espacios en blanco sin ningún número

¿Por qué? Realmente no estoy familiarizado con boost::lambda así que me podría estar perdiendo lo obvio aquí.

Por favor, no sugieren std::copy respuestas basadas: mi código real no funciona en std::vector sino en boost::fusion::vector (y std::for_each es en realidad un boost::fusion::for_each).

Respuesta

4

Por alguna razón, su código evalúa boost::format("%10d") % bl::_1 inmediatamente, en lugar de en cada invocación de la lambda. Para evitar esto, debe ajustar boost::format("%10d") en una llamada al bl::var, tal como lo hizo con std::cout.

Desafortunadamente, hacer esto requiere Boost.Lambda para deducir el tipo de devolución de la llamada a operator%, que no puede hacer. Por lo tanto, el tipo de devolución debe especificarse explícitamente, usando bl::ret. Tenga en cuenta que este tipo de devolución debe ser una referencia, para que std::cout acceda directamente al objeto devuelto en lugar de una copia del mismo.

Así obtenemos el siguiente código, que produce el resultado esperado:

std::for_each(v.begin(), v.end(), bl::var(std::cout) << 
    bl::ret<const boost::format &>(bl::var(boost::format("%10d")) % bl::_1)); 
+0

sí, esto funciona, pero no tengo idea de por qué es necesario. 'boost :: lambda :: var' solo debería ser necesario cuando ninguno de los argumentos es una expresión lambda. Apuntaba a una sintaxis agradable y concisa utilizando 'boost :: lambda' :(Lástima – icecrime

2

Mi apuesta es que te encuentras con el hecho de que un formato utilizado ya no se puede usar.

boost::format f("..."); 

std::string s = f % ... ; 
std::string s2 = f % other options...; // FAIL! f has been changed by the above use! 

En otras palabras, utilizando% en un formato realmente sustituye a los datos de la cadena con lo que% 'd en ella. Lo más interesante es que el segundo uso anterior será en silencio error.

Lo sé, es un poco contra-intuitivo, pero es lo que es.

+0

gracias por su respuesta, pero creo que el código que proporciona funciona como se espera. Para citar la documentación de boost.format "Una vez alimentados todos los argumentos, puede volcar el objeto de formato a una secuencia. [...] La cadena de resultados permanece accesible en el objeto de formato hasta que se pase otro argumento, en cuyo momento se reinicia. " El segundo '%' realmente reinicia el formato, ¡pero debería ser algo bueno en mi caso! – icecrime

+0

En mi experiencia no es así, pero si su millaje varía, sugiero ignorar mi respuesta. No tengo idea de qué otro problema podría tener. –

Cuestiones relacionadas