En utilisant boost :: format dans un boost :: lambda
-
09-10-2019 - |
Question
Pour une raison quelconque, je n'utiliser boost::format
dans un boost::lambda
. Voici un (je l'espère) la simplification compilable de mon code:
#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 première
std::for_each
produit la sortie attendue - La deuxième
std::for_each
ne sort que sans numéro espacements
Pourquoi? Je ne suis vraiment pas familier avec boost::lambda
donc je pourrais être absent de l'évidence ici.
S'il vous plaît ne suggère pas des réponses basées sur std::copy
. Mon code actuel ne fonctionne pas sur std::vector
mais boost::fusion::vector
(et std::for_each
est en fait un boost::fusion::for_each
)
La solution
Pour une raison quelconque, votre evalue de code boost::format("%10d") % bl::_1
immédiatement, plutôt que sur chaque appel du lambda.
Pour éviter cela, vous devez envelopper boost::format("%10d")
dans un appel à bl::var
, comme vous l'avez fait avec std::cout
.
Malheureusement, cette opération nécessite Boost.Lambda de déduire le type de retour de l'appel à operator%
, qu'il est incapable de le faire. Par conséquent, le type de retour doit être spécifié explicitement, en utilisant bl::ret
. Notez que ce type de retour doit être une référence, afin que std::cout
accède à l'objet retourné directement au lieu d'une copie de celui-ci.
On obtient ainsi le code suivant, qui produit le résultat attendu:
std::for_each(v.begin(), v.end(), bl::var(std::cout) <<
bl::ret<const boost::format &>(bl::var(boost::format("%10d")) % bl::_1));
Autres conseils
Mon pari est que vous êtes en cours d'exécution dans le fait qu'un format utilisé n'est plus utilisable.
boost::format f("...");
std::string s = f % ... ;
std::string s2 = f % other options...; // FAIL! f has been changed by the above use!
En d'autres termes, en utilisant% sur un format remplace en fait les données de chaîne avec tout ce que vous% 'd en elle. La chose est plus froide que la deuxième utilisation ci-dessus en silence échec.
Je sais, sorte de contre-intuitif, mais il est ce qu'il est.