OVH Cloud OVH Cloud

Boost.Lambda

5 réponses
Avatar
Marc Duflot
Bonjour.

Je ne parviens pas à utiliser l'expression cout<<_1<<endl avec
Boost.Lambda. Voici un exemple.

#include <vector>
#include <algorithm>
#include <iostream>
#include <boost/lambda/lambda.hpp>

int main()
{
using namespace std;
using namespace boost::lambda;

vector<int> v;

for_each (v.begin(), v.end(), cout << _1 << '\n'); // (1)
for_each (v.begin(), v.end(), cout << _1 << endl); // (2)
}

La forme (1) fonctionne mais la forme (2) est refusée à la compilation
avec l'erreur suivante :

no match for ‘operator<<’ in ‘boost::lambda::operator<<(A&, const
boost::lambda::lambda_functor<Arg>&) [with A = std::ostream, Arg
=boost::lambda::placeholder<1>](((const
boost::lambda::lambda_functor<boost::lambda::placeholder<1> >&)(+
boost::lambda::<unnamed>::_1))) << std::endl


Merci de m'éclairer.
Marc

5 réponses

Avatar
Stephane Wirtel
Si tu trouves une solution, cela m'intéresse.

Bonne continuation.
Avatar
Marc Duflot
Stephane Wirtel wrote:
Si tu trouves une solution, cela m'intéresse.

Bonne continuation.


J'ai trouvé l'explication suivante:

http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?action=browse&id=Suggestions_-_Lambda_Library

En bref, le problème est que endl est une fonction template dont le type
ne peut pas être déduit dans ce contexte. Il existe bien une solution
pour contourner le problème qui y est décrite mais je vais garder la
forme avec 'n'.

Avatar
Falk Tannhäuser
Marc Duflot wrote:
J'ai trouvé l'explication suivante:
http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?action= browse&id=Suggestions_-_Lambda_Library
En bref, le problème est que endl est une fonction template dont le t ype
ne peut pas être déduit dans ce contexte. Il existe bien une soluti on
pour contourner le problème qui y est décrite mais je vais garder l a
forme avec 'n'.


Effectivement, les formes
for_each (v.begin(), v.end(), cout << _1 << static_cast<ostream&(*)(os tream&)>(endl));
ou
for_each (v.begin(), v.end(), cout << _1 << &endl<char, char_traits<ch ar> >);
(ne pas oublier le '&' sous peine de se trouver enseveli sous une avalanc he
d'insultes incompréhensibles due à une ambiguïté de surcharge)
passent.
Mais il est vrai qu'il ne sert à rien de faire un flush (comme le fait endl)
à chaque coup - d'un point de vue de performance, c'est même décons eillé.
Si nécessaire, on pourra toujours ajouter un 'cout << flush' après le for_each.

Falk

Avatar
Gabriel Dos Reis
=?windows-1252?Q?Falk_Tannhäuser?= writes:

| Marc Duflot wrote:
| > J'ai trouvé l'explication suivante:
| > http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?action=browse&id=Suggestions_-_Lambda_Library
| > En bref, le problème est que endl est une fonction template dont le
| > type ne peut pas être déduit dans ce contexte. Il existe bien une
| > solution pour contourner le problème qui y est décrite mais je vais
| > garder la forme avec 'n'.
|
| Effectivement, les formes
| for_each (v.begin(), v.end(), cout << _1 << static_cast<ostream&(*)(ostream&)>(endl));
| ou
| for_each (v.begin(), v.end(), cout << _1 << &endl<char, char_traits<char> >);

C'est d'une élégance foudroyante, n'est-ce pas ?

-- Gaby
Avatar
Marc Duflot
Falk Tannhäuser wrote:
Marc Duflot wrote:

J'ai trouvé l'explication suivante:
http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?action=browse&id=Suggestions_-_Lambda_Library
En bref, le problème est que endl est une fonction template dont le
type ne peut pas être déduit dans ce contexte. Il existe bien une
solution pour contourner le problème qui y est décrite mais je vais
garder la forme avec 'n'.



Effectivement, les formes
for_each (v.begin(), v.end(), cout << _1 <<
static_cast<ostream&(*)(ostream&)>(endl));
ou
for_each (v.begin(), v.end(), cout << _1 << &endl<char,
char_traits<char> >);
(ne pas oublier le '&' sous peine de se trouver enseveli sous une avalanche
d'insultes incompréhensibles due à une ambiguïté de surcharge)
passent.


Pour la curiosité, voici un hack qui permet de garder la syntaxe dans
l'expression lambda

#include <vector>
#include <algorithm>
#include <iostream>
#include <boost/lambda/lambda.hpp>

namespace boost { namespace lambda {
::std::ostream& (*endl)(::std::ostream&)
= &::std::endl<char, ::std::char_traits<char> >;
} }

int main()
{
using namespace boost::lambda;

std::vector<int> v;

std::for_each (v.begin(), v.end(), std::cout << _1 << 'n'); // (1)
std::for_each (v.begin(), v.end(), std::cout << _1 << endl); // (2)
}

Le endl de la forme (2) est trouvé dans boost::lambda.

Bien sûr, je ne conseille pas de faire ça en pratique car un « using
namespace std; » bien placé rend l'usage de endl ambigu. De plus, si on
utilise un basic_ostream<paschar>, ça ne marche plus.

Marc