Utilizzando boost :: formato in un boost :: lambda
-
09-10-2019 - |
Domanda
Per qualche ragione, non riesco a utilizzare boost::format
in un boost::lambda
. Ecco una (si spera) compilabile semplificazione del mio codice:
#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);
}
- Il primo
std::for_each
produce l'output previsto - Il secondo
std::for_each
emette solo spazi bianchi senza numero
Perché? Io non sono davvero familiarità con boost::lambda
quindi potrei mancare l'ovvio qui.
Si prega di non suggerire risposte std::copy
base:. Il mio codice reale non funziona su std::vector
ma su boost::fusion::vector
(e std::for_each
è infatti un boost::fusion::for_each
)
Soluzione
Per qualche ragione, i vostri Esamina codice boost::format("%10d") % bl::_1
subito, piuttosto che su ogni invocazione del lambda.
Per evitare questo, è necessario avvolgere boost::format("%10d")
in una chiamata a bl::var
, proprio come avete fatto con std::cout
.
Purtroppo, facendo questo richiede Boost.Lambda di dedurre il tipo di ritorno della chiamata a operator%
, che non è in grado di fare. Pertanto, il tipo di ritorno deve essere specificato in modo esplicito, utilizzando bl::ret
. Si noti che questo tipo di ritorno deve essere un riferimento, in modo che std::cout
accede all'oggetto restituito direttamente piuttosto che una copia di esso.
Abbiamo quindi ottenere il codice seguente, che produce i risultati attesi:
std::for_each(v.begin(), v.end(), bl::var(std::cout) <<
bl::ret<const boost::format &>(bl::var(boost::format("%10d")) % bl::_1));
Altri suggerimenti
La mia scommessa è che si sta eseguendo nel fatto che un formato utilizzato non è più utilizzabile.
boost::format f("...");
std::string s = f % ... ;
std::string s2 = f % other options...; // FAIL! f has been changed by the above use!
In altre parole, utilizzando% su un formato in realtà sostituisce i dati della stringa con qualsiasi cosa% 'd in esso. La cosa più fresca è che il secondo uso sopra sarà silenziosamente non riuscire.
Lo so, sorta di contro-intuitivo, ma è quello che è.