error using lambdas: conversion from 'x' to non-scalar type 'y'

Hi, I'm rather new to lambdas. I wanted to use them to stream objects into a special stream (not a stl stream). the following code outlines the situation: ---- #include <iostream> #include <list> #include <algorithm> #include <boost/ref.hpp> #include <boost/shared_ptr.hpp> #include <boost/lambda/lambda.hpp> using namespace std; using namespace boost; using boost::lambda::_1; class MyStream { public: MyStream() {} }; class MySubStream: public MyStream { public: MySubStream(MyStream*) {} }; MyStream& operator <<(MyStream& os, const int&) { return os; } int main() { list<shared_ptr<int> > cont; MyStream osTop; MySubStream osSub(&osTop); for_each(cont.begin(), cont.end(), ref(osSub) << *_1); return 0; } ---- g++ outputs error: '/usr/include/boost/lambda/detail/operator_lambda_func_base.hpp:212: error: conversion from 'MyStream' to non-scalar type 'MySubStream' requested'. MS VC 2003.net says: boost\lambda\detail\operator_lambda_func_base.hpp(212) : error C2664: 'MySubStream::MySubStream(MyStream *)' : cannot convert parameter 1 from 'MyStream' to 'MyStream *'. The question is whether my code is correct at all and how I could use lambdas the right way. Thanks! Klaus Triendl

klaus triendl wrote: [...]
MyStream& operator <<(MyStream& os, const int&) { return os; }
int main() { list<shared_ptr<int> > cont; MyStream osTop; MySubStream osSub(&osTop);
MyStream& tmp = osSub;
for_each(cont.begin(), cont.end(), ref(osSub) << *_1);
for_each( cont.begin(), cont.end(), tmp << *_1 ); // or, if the above doesn't work - it should - for_each( cont.begin(), cont.end(), ref(tmp) << *_1 );
return 0; } ----
g++ outputs error: '/usr/include/boost/lambda/detail/operator_lambda_func_base.hpp:212: error: conversion from 'MyStream' to non-scalar type 'MySubStream' requested'.
Lambda sees that you are invoking operator<< on a MySubStream& and deduces the return type to be MySubStream&; it isn't smart enough to see that you're actually using the operator<< definition for the base class MyStream.

Peter Dimov wrote:
klaus triendl wrote:
[...]
MyStream& operator <<(MyStream& os, const int&) { return os; }
int main() { list<shared_ptr<int> > cont; MyStream osTop; MySubStream osSub(&osTop);
MyStream& tmp = osSub;
for_each(cont.begin(), cont.end(), ref(osSub) << *_1);
for_each( cont.begin(), cont.end(), tmp << *_1 );
// or, if the above doesn't work - it should -
for_each( cont.begin(), cont.end(), ref(tmp) << *_1 );
return 0; } ----
g++ outputs error: '/usr/include/boost/lambda/detail/operator_lambda_func_base.hpp:212: error: conversion from 'MyStream' to non-scalar type 'MySubStream' requested'.
Lambda sees that you are invoking operator<< on a MySubStream& and deduces the return type to be MySubStream&; it isn't smart enough to see that you're actually using the operator<< definition for the base class MyStream.
I thought that it would be converted implicitly in the end by the compiler.. Can I make it smart enough? -- Klaus

klaus triendl wrote:
Peter Dimov wrote:
Lambda sees that you are invoking operator<< on a MySubStream& and deduces the return type to be MySubStream&; it isn't smart enough to see that you're actually using the operator<< definition for the base class MyStream.
I thought that it would be converted implicitly in the end by the compiler..
There is no implicit conversion from MyStream& to MySubStream&.
Can I make it smart enough?
I showed you one way. Another would be to use ret<MyStream&> to force a specific return type: http://www.boost.org/doc/html/lambda/le_in_details.html#lambda.overriding_de...

Peter Dimov wrote:
klaus triendl wrote:
Peter Dimov wrote: Can I make it smart enough?
I showed you one way. Another would be to use ret<MyStream&> to force a specific return type:
http://www.boost.org/doc/html/lambda/le_in_details.html#lambda.overriding_de...
Thanks for pointing me in the right direction. Extending the return type deduction system is the best way for me: namespace boost { namespace lambda { template<typename T> class plain_return_type_2<bitwise_action<leftshift_action>, MySubStream, T> { public: typedef MyStream& type; }; } } -- Klaus Triendl
participants (2)
-
klaus triendl
-
Peter Dimov