El uso de impulso :: formato en un impulso :: lambda
-
09-10-2019 - |
Pregunta
Por alguna razón, no llego a utilizar boost::format
en un boost::lambda
. Aquí está una (esperemos) la simplificación compilables de mi código:
#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
sólo produce la salida espacios en blanco sin ningún número
¿Por qué? Realmente no estoy familiarizado con boost::lambda
así que puede ser que falte la obvia aquí.
Por favor, no sugieren respuestas basadas std::copy
:. Mi código real no funciona en std::vector
sino en boost::fusion::vector
(y std::for_each
es de hecho una boost::fusion::for_each
)
Solución
For some reason, your code evaluates boost::format("%10d") % bl::_1
immediately, rather than on each invocation of the lambda.
To prevent this, you need to wrap boost::format("%10d")
in a call to bl::var
, just as you have done with std::cout
.
Unfortunately, doing this requires Boost.Lambda to deduce the return type of the call to operator%
, which it is unable to do. Therefore the return type must be specified explicitly, using bl::ret
. Note that this return type must be a reference, in order that std::cout
accesses the returned object directly rather than a copy of it.
We thus get the following code, which produces the expected output:
std::for_each(v.begin(), v.end(), bl::var(std::cout) <<
bl::ret<const boost::format &>(bl::var(boost::format("%10d")) % bl::_1));
Otros consejos
My bet is that you're running into the fact that a format used is no longer usable.
boost::format f("...");
std::string s = f % ... ;
std::string s2 = f % other options...; // FAIL! f has been changed by the above use!
In other words, using % on a format actually replaces the string data with whatever you %'d into it. The cooler thing is that the second use above will silently fail.
I know, kind of counter-intuitive, but it is what it is.