• 12
• 12
• 9
• 10
• 13

# boost::lambda

This topic is 3881 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm trying to figure out how to use the boost.lambda library, and I'm having some issues, probably stupid ones, but still, issues. In the following code I want to remove all obects from m_devices that only have 1 remaining reference (unique() returns true). Yes, I know that this would be pretty easy, using regular function pointers, and the like, however, I'm trying to learn this library. What am I doing wrong? I would also appreciate any pointers for using boost.lambda Whenever I compile the following code on VS2005 I get the following errors:
Quote:
 Warning 1 warning C4512: 'boost::lambda::identity' : assignment operator could not be generated c:\program files (x86)\boost\boost_1_34_0\boost\lambda\detail\lambda_functor_base.hpp 43 Warning 2 warning C4512: 'boost::lambda::lambda_functor' : assignment operator could not be generated c:\program files (x86)\boost\boost_1_34_0\boost\lambda\detail\lambda_functors.hpp 204 Warning 3 warning C4180: qualifier applied to function type has no meaning; ignored c:\program files (x86)\boost\boost_1_34_0\boost\lambda\detail\lambda_traits.hpp 255 Error 4 error C2679: binary '->*' : no operator found which takes a right-hand operand of type 'overloaded-function' (or there is no acceptable conversion) c:\users\diltsman\documents\visual studio 2005\projects\operationaardvark\socketstream\socketfactory.cpp 14
#pragma once

#include <string>
#include <map>
#include <boost/shared_ptr.hpp>

#include "SocketDevice.h"

namespace Socket
{
class SocketFactory
{
public:
SocketFactory(std::string Host, std::string Port);
virtual ~SocketFactory(void);
protected:
std::pair<std::string, std::string> m_dest;
boost::shared_ptr<SocketDevice> m_device;
static std::map<std::pair<std::string, std::string>, boost::shared_ptr<SocketDevice>> m_devices;
private:
void RemoveUnreferencedSockets(void);
};
};


#include "SocketFactory.h"
#include <boost/lambda/lambda.hpp>
#include <boost/bind.hpp>

Socket::SocketFactory::~SocketFactory(void)
{
}

void Socket::SocketFactory::RemoveUnreferencedSockets(void)
{
std::remove_if(Socket::SocketFactory::m_devices.begin(),
Socket::SocketFactory::m_devices.end(),
boost::lambda::_1 ->* &std::pair<std::pair<std::string, std::string>, boost::shared_ptr<SocketDevice> >::second
->* boost::shared_ptr<SocketDevice>::unique);
}



##### Share on other sites
Here is a short - and probably incomplete - answer (seems like I'm posting a lot of those lately!).

I'm not an expert on the Boost.Lambda library and its usage, but I don't think it can be used as in your example.

Although I haven't studied the implementation, I'm guessing that the Lambda library overloads various operators (==, <, >, =, etc.) for the lambda 'placeholder' type (that is, the type of which e.g. _1 is an instance), and that these operators then return a function object, which is what is actually used by the called function (remove_if(), in your example).

As such, expressions such as _1->SomeFunction(), while admittedly intuitive, are an error (presumably because, before it does anything else, the compiler must attempt to resolve SomeFunction() with respect to the Lambda placeholder type, which it cannot do).

I must stress here that I'm not positive that the above information is correct, but I don't have time to investigate it further at the moment.

Two other quick notes. First, the above issues aside, I'm not sure what you're trying to do there with the third argument to remove_if() (keep in mind that the argument to the functor will be a reference to the container element type). Also, you might check the docs for remove_if(); currently you're ignoring the return value, which probably isn't what you intend.

I lied, there's one more thing: remove_if() cannot be used on sorted associative containers such as map, so in any case you'll need to use some other method to remove the unwanted elements.

##### Share on other sites
Quote:
 Original post by jykHere is a short - and probably incomplete - answer (seems like I'm posting a lot of those lately!).I'm not an expert on the Boost.Lambda library and its usage, but I don't think it can be used as in your example.Although I haven't studied the implementation, I'm guessing that the Lambda library overloads various operators (==, <, >, =, etc.) for the lambda 'placeholder' type (that is, the type of which e.g. _1 is an instance), and that these operators then return a function object, which is what is actually used by the called function (remove_if(), in your example).As such, expressions such as _1->SomeFunction(), while admittedly intuitive, are an error (presumably because, before it does anything else, the compiler must attempt to resolve SomeFunction() with respect to the Lambda placeholder type, which it cannot do).I must stress here that I'm not positive that the above information is correct, but I don't have time to investigate it further at the moment.Two other quick notes. First, the above issues aside, I'm not sure what you're trying to do there with the third argument to remove_if() (keep in mind that the argument to the functor will be a reference to the container element type). Also, you might check the docs for remove_if(); currently you're ignoring the return value, which probably isn't what you intend.I lied, there's one more thing: remove_if() cannot be used on sorted associative containers such as map, so in any case you'll need to use some other method to remove the unwanted elements.

Yeah, your last statement is what I get for leaving my STL reference at work. Hard to find a decent reference.

As for calling a member function from a lambda function, I thought that was possible. From the documentation for boost.lambda:
Quote:
 Member pointer operatorThe member pointer operator operator->* can be overloaded freely. Hence, for user defined types, member pointer operator is no special case. The built-in meaning, however, is a somewhat more complicated case. The built-in member pointer operator is applied if the left argument is a pointer to an object of some class A, and the right hand argument is a pointer to a member of A, or a pointer to a member of a class from which A derives. We must separate two cases: The right hand argument is a pointer to a data member. In this case the lambda functor simply performs the argument substitution and calls the built-in member pointer operator, which returns a reference to the member pointed to. For example: struct A { int d; };A* a = new A(); ...(a ->* &A::d); // returns a reference to a->d (_1 ->* &A::d)(a); // likewiseThe right hand argument is a pointer to a member function. For a built-in call like this, the result is kind of a delayed member function call. Such an expression must be followed by a function argument list, with which the delayed member function call is performed. For example: struct B { int foo(int); };B* b = new B(); ...(b ->* &B::foo) // returns a delayed call to b->foo // a function argument list must follow(b ->* &B::foo)(1) // ok, calls b->foo(1)(_1 ->* &B::foo)(b); // returns a delayed call to b->foo, // no effect as such(_1 ->* &B::foo)(b)(1); // calls b->foo(1)

I was trying to follow their examples, but obviously screwed up somewhere, so if someone could point out my mistake I would appreciate it.

##### Share on other sites
You're missing an address-of operator on boost::shared_ptr<SocketDevice>::unique, but adding it seems to lead to even bigger problems [smile] 3 new errors, only the first 2 relate to the use of boost::lambda though, with the 3rd being because you're trying to use std::remove_if on an associative container.

##### Share on other sites
Quote:
 Original post by joanusdmentiaYou're missing an address-of operator on boost::shared_ptr::unique, but adding it seems to lead to even bigger problems [smile] 3 new errors, only the first 2 relate to the use of boost::lambda though.

Looks like you were right...On both accounts. Now what am I missing? Once I add that & I now get the following errors:
Quote:
 Warning 1 warning C4512: 'boost::lambda::identity' : assignment operator could not be generated c:\program files (x86)\boost\boost_1_34_0\boost\lambda\detail\lambda_functor_base.hpp 43 Warning 2 warning C4512: 'boost::lambda::lambda_functor' : assignment operator could not be generated c:\program files (x86)\boost\boost_1_34_0\boost\lambda\detail\lambda_functors.hpp 204 Warning 3 warning C4512: 'boost::lambda::identity' : assignment operator could not be generated c:\program files (x86)\boost\boost_1_34_0\boost\lambda\detail\lambda_functor_base.hpp 43 Warning 4 warning C4512: 'boost::lambda::lambda_functor' : assignment operator could not be generated c:\program files (x86)\boost\boost_1_34_0\boost\lambda\detail\lambda_functors.hpp 204 Error 5 error C2451: conditional expression of type 'boost::lambda::detail::member_pointer_caller' is illegal c:\program files (x86)\microsoft visual studio 8\vc\include\algorithm 87 Error 6 error C2675: unary '!' : 'boost::lambda::detail::member_pointer_caller' does not define this operator or a conversion to a type acceptable to the predefined operator c:\program files (x86)\microsoft visual studio 8\vc\include\algorithm 1240 Error 7 error C2582: 'operator =' function is unavailable in 'std::pair<_Ty1,_Ty2>' c:\program files (x86)\microsoft visual studio 8\vc\include\algorithm 1241

##### Share on other sites
Quote:
 Original post by DiltsmanAs for calling a member function from a lambda function, I thought that was possible.
Yup, looks like I was wrong about that (as I suspected might be the case). I remember trying that at one point with no success, but maybe I just wasn't doing it right :)

##### Share on other sites
Quote:
 Original post by DiltsmanLooks like you were right...On both accounts. Now what am I missing? Once I add that & I now get the following errors:

Quote:
 Error 5 error C2451: conditional expression of type 'boost::lambda::detail::member_pointer_caller' is illegal c:\program files (x86)\microsoft visual studio 8\vc\include\algorithm 87 Error 6 error C2675: unary '!' : 'boost::lambda::detail::member_pointer_caller' does not define this operator or a conversion to a type acceptable to the predefined operator c:\program files (x86)\microsoft visual studio 8\vc\include\algorithm 1240

These errors are the ones of interest, the 3rd is because it's trying to move 'removed' values to the end of the container (which obviously doesn't make sense or work for associative containers). It looks like the compiler's not seeing the operator() on member_pointer_caller, but why that is I've got no idea.