Reputation: 10658
I have some code that can greatly be reduced in complexity by using lambdas. However unfortunately we have to use a compiler that does not fully support C++11 and we cannot easily switch. Now the question is how to keep the logic as close as possible to a lambda-expression with features not available (i.e. std::function
is available, lambdas are not).
The usual solution is to define the functor somewhere else and then use it at the appropriate place:
struct functor{
functor( type & member ) : m_member( member ) {}
void operator()( ... ) {...}
type & m_member;
};
void function() {
use_functor( functor(...) );
}
I am very much used to this pattern, although I dislike it a lot. The main reason for not defining the class is usually that I the functor will be used within a STL and templates do not like structs defined inline of a function. However in my case the use_functor()
function will be a normal method, so I can define the functor inside of the function itself (each functor is only used within one function).
void function() {
struct functor{
functor( type & member ) : m_member( member ) {}
void operator()( ... ) {...}
type & m_member;
};
use_functor( functor(...) );
}
This seems somewhat improved, but still requires a lot more ugly code that I would like. For example I would like to get rid of the name of the functor altogether. I know it is possible to create an anonymous struct, if I only ever use one value.
void function() {
struct{
// functor( type member ) : m_member( member ) {}
void operator()( ... ) {...}
// type & m_member;
} callback ;
use_functor( callback );
}
However at this point I have no clue on how to provide the necessary data members. Since the struct is anonymous it does not have a constructor. I could easily set the member, because it is public, but again this would add a line which I dislike.
The goal is to leave it in a state that as little as possible needs to be changed once we switch to a compiler that has clean lambdas which would allow to eliminate this problem altogether.
How would you go about doing this?
Upvotes: 5
Views: 267
Reputation: 9018
Expanding on the answer by awoodland:
#define MY_LAMBDA(name, memberType, memberValue, body) \
struct { \
void operator()( ... ) body \
memberType & memberValue; \
} name = {memberValue}
void function() {
type thing_to_capture;
MY_LAMBDA(callback, type, thing_to_capture
{
std::cout << thing_to_capture << std::endl;
});
use_functor( callback );
}
You can use MY_LAMBDA
anywhere you can define a struct. Unfortunately, without variadic macros, you have to wrap all captured objects into a single object, and you have to specify the type of that object in the "lambda declaration"
Also note that the equivalent using a lambda would be:
void function() {
type thing_to_capture;
auto callback = [&thing_to_capture]()
{
std::cout << thing_to_capture << std::endl;
};
use_functor( callback );
}
Upvotes: 0
Reputation: 1742
You could try boost lambda library or boost::phoenix. They are both designed to do lambda style operations without actual lambda support. Since they are template based, errors can be difficult to debug when something doesn't work as expected.
Upvotes: 0
Reputation: 88741
With regards to the initalisation of the member variables of an anonymous struct
without a constructor you can do:
void function() {
type the_thing;
struct {
void operator()( ... ) {...}
type & m_member;
} callback = {the_thing};
use_functor( callback );
}
to set the type &
reference m_member
in callback
.
Upvotes: 1