This is actually possible and not that ugly with either the Boost Lambda Library, Boost.Bind or Boost.Phoenix's bind
.
All placeholders and binder types returned from a call to bind
from any of those libraries will have all kinds of operators overloaded so you can easily create expressions with them "on the fly". With Boost.Bind:
#include <iostream>
#include <boost/bind.hpp>
struct X{ bool a, b; };
int main(){
using boost::bind;
auto op = bind(&X::a, _1) && !bind(&X::b, _1);
X x{true, false};
auto test = bind(op, x);
if(test())
std::cout << "Yay\n";
}
Live example.
This, of course, has the obvious disadvantage of going through member pointers. Also, in C++03, you had a mighty problem writing out the type of such a "lambda", since it's a huge templated mess. The little example above will yield a huge name, as can be seen here. And since a library solution was not "the best it could be", the standard committee added lambdas to the language. Yay.
Note that, while C++11's std::bind
looks similar on the surface, it's a pure binder. It does not allow you to create expressions on-the-fly as it does not overload any operators for any related types.