
Is it possible to invoke user defined streaming operators within boost lambda functions? In this style #include <iostream> #include <map> #include "boost/lambda/lambda.hpp" using namespace std; ostream & operator << ( ostream & ostrm, pair<string, string> const & input ); ostream & operator << ( ostream & ostrm, map<string, string> & inputs ) { using namespace boost :: lambda; for_each ( inputs.begin( ), inputs.end( ), ostrm << _1 << '\n' ); return ostrm; } Is this basically undoable, or am I doing it wrong? Also, does the online Comeau compiler understand the boost include directives? Thanks, Rob.

on Fri Jul 11 2008, "Robert Jones" <robertgbjones-AT-gmail.com> wrote:
Is it possible to invoke user defined streaming operators within boost lambda functions? In this style
#include <iostream> #include <map> #include "boost/lambda/lambda.hpp"
using namespace std;
ostream & operator << ( ostream & ostrm, pair<string, string> const & input );
ostream & operator << ( ostream & ostrm, map<string, string> & inputs ) { using namespace boost :: lambda;
for_each ( inputs.begin( ), inputs.end( ), ostrm << _1 << '\n' ); return ostrm; }
Yes, something like that works.
Is this basically undoable, or am I doing it wrong?
Why would you think either one was true? Note that std::endl can cause you big troouble, but since you're using '\n' above I don't see a reason to worry. You do need something like "using namespace boost::lambda;" to make "_1" valid, though.
Also, does the online Comeau compiler understand the boost include directives?
That's a question for Comeau. HTH, -- Dave Abrahams BoostPro Computing http://www.boostpro.com

AMDG David Abrahams wrote:
on Fri Jul 11 2008, "Robert Jones" <robertgbjones-AT-gmail.com> wrote:
using namespace std;
ostream & operator << ( ostream & ostrm, pair<string, string> const & input );
Yes, something like that works.
Except that the overloads can't be found by ADL. In Christ, Steven Watanabe

on Fri Jul 11 2008, Steven Watanabe <watanabesj-AT-gmail.com> wrote:
AMDG
David Abrahams wrote:
on Fri Jul 11 2008, "Robert Jones" <robertgbjones-AT-gmail.com> wrote:
using namespace std;
ostream & operator << ( ostream & ostrm, pair<string, string> const & input );
Yes, something like that works.
Except that the overloads can't be found by ADL.
Good catch! Yeah, you can't legally define streaming for std::pair<> that will work in a generic context. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

On Fri, Jul 11, 2008 at 5:33 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
David Abrahams wrote:
on Fri Jul 11 2008, "Robert Jones" <robertgbjones-AT-gmail.com> wrote:
using namespace std;
ostream & operator << ( ostream & ostrm, pair<string, string> const & input );
Yes, something like that works.
Except that the overloads can't be found by ADL.
I'm sorry, I'm not quite following! I understand ADL in general, but not how it applies specifically here. What overloading is being found/not found by ADL in this context? Thanks Steven, Rob.

AMDG Robert Jones wrote:
I'm sorry, I'm not quite following! I understand ADL in general, but not how it applies specifically here. What overloading is being found/not found by ADL in this context?
The overload of operator<< for std::pair is not found by Boost.Lambda. In Christ, Steven Watanabe

On Fri, Jul 11, 2008 at 7:08 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
Robert Jones wrote:
I'm sorry, I'm not quite following! I understand ADL in general, but not how it applies specifically here. What overloading is being found/not found by ADL in this context?
The overload of operator<< for std::pair is not found by Boost.Lambda.
This much I have discovered painfully by trial and error - the bit I don't understand is why! Also, it would be very handy if you can suggest a method of achieving the effect I'm looking for. Thanks, Rob.

on Fri Jul 11 2008, "Robert Jones" <robertgbjones-AT-gmail.com> wrote:
On Fri, Jul 11, 2008 at 7:08 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
Robert Jones wrote:
I'm sorry, I'm not quite following! I understand ADL in general, but not how it applies specifically here. What overloading is being found/not found by ADL in this context?
The overload of operator<< for std::pair is not found by Boost.Lambda.
This much I have discovered painfully by trial and error - the bit I don't understand is why!
Because was not in scope at the point where the lambda's operator() is defined, and it isn't defined in a namespace associated with any of the arguments you passed to it (ostream and std::pair<...>). Those are the lookup rules for unqualified calls in templates. namespace bll { template <class T> void f(T x) { // looks backwards from this point for op<< defined in // namespaces :: and ::bll::. Looks backwards from the // point of instantiation for op<< defined in any // namespaces associated with T. x << x; } }; I think I got that right.
Also, it would be very handy if you can suggest a method of achieving the effect I'm looking for.
Depends what effect that is; it may or may not be achievable. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

AMDG Robert Jones wrote:
On Fri, Jul 11, 2008 at 7:08 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
The overload of operator<< for std::pair is not found by Boost.Lambda.
This much I have discovered painfully by trial and error - the bit I don't understand is why!
There are two ways that functions can be found from within a template. The first is the functions which are visible at the point where the template is defined. Your overload of operator<< is not declared when the Boost.Lambda stuff is included, so it won't be found that way. The second way is through ADL. ADL searches /only/ in namespaces associated with the argument types. In this case only namespace std is associated with the argument types, not the global namespace, so operator<< can't be found that way either.
Also, it would be very handy if you can suggest a method of achieving the effect I'm looking for.
There isn't a legal way. The standard forbids adding functions to namespace std. In Christ, Steven Watanabe

On Fri, Jul 11, 2008 at 7:30 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
There are two ways that functions can be found from within a template. The first is the functions which are visible at the point where the template is defined. Your overload of operator<< is not declared when the Boost.Lambda stuff is included, so it won't be found that way.
Ah, right, got it now. My misunderstanding was in the point at which visibility of my pair streaming operator counted. I had thought it was at the point of invocation of the lambda function, whereas in fact it is the point of definition of the lambda function (ie in the lambda header). I guess defining streaming operators outside the namespace in which the class being streamed is defined is fairly unusual, in fact it probably only occurs for members of the std namespace in practise, so I have been unfortunate to bump into an odd set of circumstances. Thanks to Steven and David for putting me straight on this one. Rob.

On Fri, Jul 11, 2008 at 4:41 PM, David Abrahams <dave@boostpro.com> wrote: Note that std::endl can cause you big troouble, but since you're using
'\n' above I don't see a reason to worry. You do need something like "using namespace boost::lambda;" to make "_1" valid, though.
Back in the office on Monday morning, and applying my new found knowledge my Boost-using code compiles perfectly, but for one little snag! For brevity and clarity I posted example code using '\n' line terminators. However my real code uses endl - which is indeed causing me big troouble! Are there any techniques for successfully using std::endl in lamda functions? Thanks, Rob.

on Mon Jul 14 2008, "Robert Jones" <robertgbjones-AT-gmail.com> wrote:
On Fri, Jul 11, 2008 at 4:41 PM, David Abrahams <dave@boostpro.com> wrote:
Note that std::endl can cause you big troouble, but since you're using '\n' above I don't see a reason to worry. You do need something like "using namespace boost::lambda;" to make "_1" valid, though.
Back in the office on Monday morning, and applying my new found knowledge my Boost-using code compiles perfectly, but for one little snag!
For brevity and clarity I posted example code using '\n' line terminators. However my real code uses endl - which is indeed causing me big troouble!
Are there any techniques for successfully using std::endl in lamda functions?
Not any good ones. The problem is that endl is a function template and ostream << std::endl; matches the operator<< overload for stream manipulators, which are function pointers, something like: ostream& operator<<( ostream, some-concrete-function-pointer-type ); so the compiler implicitly specializes std::endl<X...> so that it gets the right function pointer. It's nasty. I do this if I really, really, really want to write endl instead of '\n' (not that I ever want that ;-> ): struct endl_ { friend ostream& operator<<(ostream& x, endl_) { x << std::endl; return x; }; } endl; Then I'd just stream my own endl. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

David Abrahams wrote:
on Mon Jul 14 2008, "Robert Jones" <robertgbjones-AT-gmail.com> wrote:
On Fri, Jul 11, 2008 at 4:41 PM, David Abrahams <dave@boostpro.com> wrote:
Note that std::endl can cause you big troouble, but since you're using '\n' above I don't see a reason to worry. You do need something like "using namespace boost::lambda;" to make "_1" valid, though.
Back in the office on Monday morning, and applying my new found knowledge my Boost-using code compiles perfectly, but for one little snag!
For brevity and clarity I posted example code using '\n' line terminators. However my real code uses endl - which is indeed causing me big troouble!
Are there any techniques for successfully using std::endl in lamda functions?
Not any good ones. The problem is that endl is a function template and
ostream << std::endl;
matches the operator<< overload for stream manipulators, which are function pointers, something like:
ostream& operator<<( ostream, some-concrete-function-pointer-type );
so the compiler implicitly specializes std::endl<X...> so that it gets the right function pointer. It's nasty.
I don't know, phoenix has been using std::endl since day one. All the tests and examples I have use std::endl, not '\n'. I don't know now the exact technique that I did, but I recall working around this a long time ago. I'll go dig it up. I never really understood why lambda barfs with std::endl. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net

On Mon, 14 Jul 2008 07:08:35 -0600, David Abrahams <dave@boostpro.com> wrote: [skip]
I do this if I really, really, really want to write endl instead of '\n' (not that I ever want that ;-> ): [skip]
Well, as it was painfully discovered in not-quite-related project, std::endl has an effect of calling "flush" on stream, so you do have to use "endl" instead of just '\n' sometimes... Thanks, Andrey

Robert Jones wrote:
On Fri, Jul 11, 2008 at 4:41 PM, David Abrahams <dave@boostpro.com> wrote:
Note that std::endl can cause you big troouble, but since you're using
'\n' above I don't see a reason to worry. You do need something like "using namespace boost::lambda;" to make "_1" valid, though.
Back in the office on Monday morning, and applying my new found knowledge my Boost-using code compiles perfectly, but for one little snag!
For brevity and clarity I posted example code using '\n' line terminators. However my real code uses endl - which is indeed causing me big troouble!
Are there any techniques for successfully using std::endl in lamda functions?
FWIW, std::endl is ok with Phoenix. Regards, -- Joel de Guzman http://www.boostpro.com http://spirit.sf.net
participants (5)
-
Andrey Tcherepanov
-
David Abrahams
-
Joel de Guzman
-
Robert Jones
-
Steven Watanabe