Hosted by Get QuickFunctor (C++ Functor Library) at SourceForge.net. Fast, secure and Free Open Source software downloads
QuickFunctor
About QuickFunctor
The QuickFunctor library consists of a collection of template classes and global functions to facilitate creation of and working with "functors", or "function objects", i.e. classes implementing an operator(). The functors in QuickFunctor are a substantial improvement (IMHO) over what the standard provides, with things like composition, expressions, "transform" operations, and even the naming convention.
Obviously, the work in the functor area didn't stop after the release of the last standard; there are related things in Boost, TR1, Loki and perhaps other places, but I think QuickFunctor is worth a look.
Note: to draw attention to some important things, an yellow background combined with a bold font will be used throught this page.


Content
Origin and acknowledgements
After trying several times to use the functors from the standard library and getting frustrated that it took too long to figure out how to do things, and that some things that I thought were reasonable to do just couldn't be done (or at least I was unable to find a way to do them), and after taking a quick look at other functor implementations, I started to develop QuickFunctor, with the declared purpose to create a library that allows its users to do pretty much anything that is reasonable to do with functors, and do it as easily and as efficiently as possible.
Many "idea leaders" in the C++ community (Bjarne Stroustrup, Scott Meyers, Herb Sutter, Daveed Vandevoorde, Nicolai Josuttis among them) advocate using functors, and I find their arguments persuasive. The standard library provides an implementation for functors, in the <functional> header, but from my point of view it has some drawbacks and limitations, which were significant enough to make me decide to write my own QuickFunctor, which I think has several advantages:
Highlights While the code of QuickFunctor is entirely new, it should be quite easy to notice that it is highly influenced by the interface of Alexander Stepanov's STL library and by Andrei Alexandrescu's "Modern C++ Design" book.
Why use QuickFunctor?
Here are some reasons to use functors from QuickFunctor:
Installation and testing
Download and unpack QuickFunctor and then modify the "additional include directories" in your IDE to add the directory include from wherever you unpacked QuickFunctor. Or move the directory somewhere else and specify that new place. The include directory is the only one you really need. The others are examples, documentation, ... Or, if you use a command line compiler, keep in mind to pass it the location of the include directory when you try to compile something.
To check that it works, you should be able to create an executable file from the source files in the main_tests directory (FunctorTst.cpp and main.cpp) and from other_tests (Functor.cpp, FunctorExpressionsTst.cpp and NumericCommonTypesTst.cpp). If you can't create the executable, there's no point in going further. You need to change or upgrade your compiler (well, or you can try to make changes in the library, to accommodate your compiler, but that's not going to be easy). That executable should produce an output similar to those in the directory results (keeping in mind that the order in which those tests are run is undetermined; so if you want to capture the output and do a comparison you might need to move things around in a text editor).
If you have Eclipse with CDT, you might try to import the included Eclipse project, in the root directory. I'm not sure if it's supposed to work, especially if you have a different version of Eclipse or CDT, but it may be worth giving it a try.
Developing code that uses QuickFunctor
First of all, you need to install it and you need a pretty new compiler. Old compilers are quite likely to be unable to deal with QuickFunctor. Here's what I currently know (as of 23 August 2007):
Please let me know if it works (or not) on your (different) system. Attaching the output of the test programs would be nice too. (See the e-mail address at the end of the file.)
Also, remember that everything is in the pearl namespace.
I would suggest this strategy for getting started with QuickFunctor:
An example using functors
Here's an example of what can be done with these functors. It's about a vector of cars and searching through it. I hope it's quite self-evident, but here are a few things worth noticing: This example is meant to be looked at, but it's probably a good idea to compile it too; you may want to check the installation section above. You'll have to download and unpack QuickFunctor, copy this example code to a .cpp file and compile that file, making sure that you pass to the compiler the include directory from where you unpacked QuickFunctor. With GCC it's the -I option. Various IDEs and compilers have their own ways of specifying where the "additional include directories" are. (The file main_tests/FunctorTst.cpp has a slightly modified version of this example.)
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>

#include <FullFunctor.h>

using namespace std;
using namespace pearl;

struct Car
{
    string make;
    string model;
    int mpg;

    Car(const string& make, const string& model, int mpg) : make(make), model(model), mpg(mpg) {}
};

ostream& operator<<(ostream& out, const Car& car)
{
    out << car.make << " " << car.model << " " << car.mpg;
    return out;
}

// Finds the cars that satisfy some given condition and displays them.
// To do so it moves them to the beginning of the vector.
void findCars(vector<Car>& v, const Functor<bool (Car&)>& test)
{
    vector<Car>::iterator it;
    it = partition(v.begin(), v.end(), test);

    cout << "found " << it - v.begin() << " result(s):\n------------------\n";
    for (vector<Car>::iterator it1 = v.begin(); it1 != it; ++it1)
    {
        cout << (*it1) << endl;
    }
    cout << "**************************************\n";
}

bool hasTdi(const string& s)
{
    return string::npos != s.find_first_of("TDI");
}

void sampleUsage()
{
    vector<Car> v;
    cout << "=========================== sampleUsage() ========================================\n";
    v.push_back(Car("Toyota", "Corolla", 29));
    v.push_back(Car("VW", "Golf TDI", 41));
    v.push_back(Car("Toyota", "Land Cruiser", 14));
    v.push_back(Car("Toyota", "Avalon", 23));
    v.push_back(Car("Toyota", "Prius", 48));
    v.push_back(Car("VW", "Jetta", 32));
    v.push_back(Car("Honda", "Accord V6", 24));
    v.push_back(Car("Honda", "Accord V4", 27));

    cout << "Cars that have at least 23 mpg\n";
    findCars(v, mkF(&Car::mpg) >= 23);

    cout << "Cars that have the mpg between 23 and 41\n";
    findCars(v, mkF(&Car::mpg) >= 23 && mkF(&Car::mpg) <= 41);

    cout << "Toyotas that have at least 25 mpg\n";
    findCars(v, mkF(&Car::make) == "Toyota" && mkF(&Car::mpg) >= 25);

    vector<Car>::iterator it;
    it = find_if(v.begin(), v.end(), mkF(hasTdi).comp<1>(mkF(&Car::model)));
    //  mkF(hasTdi).o(mkF(&Car::model)) is a shortcut for the test above
    cout << "A car that has TDI: " << (*it) << endl;
}

int main()
{
    sampleUsage();
}


/*output:
=========================== sampleUsage() ========================================
Cars that have at least 23 mpg
found 7 result(s):
------------------
Toyota Corolla 29
VW Golf TDI 41
Honda Accord V4 27
Toyota Avalon 23
Toyota Prius 48
VW Jetta 32
Honda Accord V6 24
**************************************
Cars that have the mpg between 23 and 41
found 6 result(s):
------------------
Toyota Corolla 29
VW Golf TDI 41
Honda Accord V4 27
Toyota Avalon 23
Honda Accord V6 24
VW Jetta 32
**************************************
Toyotas that have at least 25 mpg
found 2 result(s):
------------------
Toyota Corolla 29
Toyota Prius 48
**************************************
A car that has TDI: VW Golf TDI 41
*/
Note. If you can't compile this example you should revisit the installation section, above.
I would like to suggest an exercise: try to redo this example with the standard library or with your favorite functor library, just to see what it takes and how easy is it to do it. You'll probably want to add "getter" methods for the data members, to be able to create any functors out of them. But even if you add the "getters", you might have trouble using and combining them. Also, note that most of the code above deals with preparing the vector and displaying the results. There are just a few lines that have anything to do with functors.
You can find my own attempt at a Boost porting below. Please don't hesitate to write me if you have a better approach. I'm not really knowledgeable about Boost, so there might be simpler ways to do what I did.
Reference
A detailed description of QuickFunctor, fully supported by examples.
Types of functors
Functors are objects of various classes. Any functor has exactly one signature, which is a function signature enclosed in brackets <R (P1, P2, ... , Pn)>. Having that signature means that it has a member function R operator()(P1, P2, ... , Pn) const, so it takes arguments of types P1, P2, ... Pn and returns R. The maximum number of parameters is determined when generating the file Functor.h (see Other notes, below); by default it's 3, and so "n" can take any value between 0 and 3. When n is 0, it means that there are no parameters: the signature <R ()> corresponds to a member function R operator()() const, taking no parameters.
A way to classify them would be into "unnamed functors" and "named functors". There are many different functor classes, which, BTW, are template classes, whose template parameters are often other functor classes, so they are usually pretty complex; but the end user doesn't need to know about them, because they should never be used directly. While this complexity doesn't prevent them from being passed to standard algorithms, there are two issues with them: on the one hand it is very cumbersome to have a variable or a parameter with such a type, and on the other hand it doesn't allow genericity. To address these issues, "named functors" have been introduced. They have a simple type, matching their signature. The type Functor<R (P1, P2, ... , Pn)> is a functor with the signature <R (P1, P2, ... , Pn)>. The type Functor<R (P1, P2, ... , Pn)> can easily be used for variables or parameters. The "unnamed" functors are all the others, created by mkF or by expressions or operations on existing functors. Apart from the fact that the template arguments of the named functors consist of their signature, while the template arguments of the unnamed functors are usually complex and hard to deal with directly, both named and unnamed functors behave the same and support the same operations.
The functors from QuickFunctor are immutable. Once they are created, they don't change. The only thing you can do to a functor variable is to assign it a new value. Apart from operator=(), they only have const methods. Named functors can be assigned any functor (named or unnamed) that has the same signature.
A named functor just containes a wrapper object, which contains a pointer to another (usually unnamed) functor, which has the actual implementation. Initially that wrapper used a class called SharedPtr to handle its pointer. Basically, that shared the same pointer among several named functors. Starting with version 0.8.1.0, this is the default, but you can also use other kinds of "smart pointers". The other one provided is ClonedPtr, which does a "deep clone" of the object pointed to on construction or assignment. You can also write your own. It has to support a simple interface, described at the beggining of the file SmartPointers.h. Another one that would be useful but is not provided is a "synchronized SharedPtr". SharedPtr's functions are "non-synchronized", so if you call them from different threads for objects that share a pointer you may leave an object of the class RefCntHolder (which is an internal class of SharedPtr) in an inconsistent state, when those threads are simultaneously manipulating references to the same underlying pointer. A "synchronized SharedPtr" is not provided because it can't be done portably with the standard library only. You can write your own, though, and, upon request, I'll provide information about how to do this if what I said here is not enough.
There is a price to pay for the convenience of named functors: they need more memory, they need heap memory, and invoking them causes a virtual function call. The unnamed functors only use the stack (unless allocated with new) and have no virtual functions. Usually this is of little importance, but sometimes it can noticeably slow down a call (if it's in the innermost loop): on the one hand the virtual call itself usually takes longer, and on the other hand the compiler will be more limited in the optimizations it can perform.
In the examples that follow, named functors will be used a lot. That is done mainly to show what are the signatures of the functors involved, but it could have been avoided and it's generally not a good practice to follow in real-world usage of QuickFunctor.
Creating functors
Creating functors is not done by calling a constructor, but by calling mkF and its variants, or by calling functor operations on existing functors, or by using expressions.
Firstly, there's mkF. This will create a functor from (almost) any function, variable, constant or numeric or string literal. (There are some exceptions when dealing with classes that don't have a copy constructor.)
Sometimes we'd like to create a functor with a different signature than what mkF would create; perhaps one that takes as its first parameter a pointer to an object, rather than a reference. Or one that returns a const string& rather than a string. Sometimes these can be done by using composition, casting or other operations, but it's usually more convenient to use one of the "modifiers" (or "suffixes") of mkF.
For functors created from data only (i.e. not from functions) there are mkFC, mkFR and mkFCR. While mkF creates a functor that returns some value type V, these variants return const V, V& and const V&, respectively.
For functors created by mkF from members (data or functions) of a class C, the first parameter of the functor is generally &C, except for const member functions, for which it is const C&. If that parameter should rather be a pointer (C* or const C*), the easiest way to do it is to add an "A" suffix to mkFXX: mkFA, mkFCA, mkFRA and mkFCRA. These will probably be most useful in code that deals with containers of (smart) pointers to classes. (Note that these are "convenience" functions; the same result could be obtained by using operations or composition on the "reference" functions: mkFA(f) <=> mkF(f).addr<1>() <=> mkF(f).comp<1>(mkF(addr<C>)) ).
When using named functor types, you may specify a "pointer use policy", to describe how the named functors should handle internally pointers to other functors. By default, SharedPtr is used, which shares an existing pointer when a named functor with the same type (including both signature and "pointer use policy") is used as a parameter to the copy constructor of a new named functor or to the operator=() of an existing named functor. This is the default, and so Functor<int (int), SharedPtr> is equivalent to just Functor<int (int)>. The alternative is ClonedPtr, which is recommended to be used when passing named functors among threads, to avoid issues that may result from the fact that SharedPtr's implementation is not synchronized. ClonedPtr should also probably be used when writing your own, mutable functors, derived from FBase.
Here's how the copy constructor and operator=() work for named functors. They can have a parameter that must be a functor with the same signature. If that functor is also a named functor with the same "pointer use policy", that policy will be taken into consideration and used appropriately. Otherwise, the parameter will be considered "generic" and a new wrapper will be created to hold a pointer to a copy of this parameter. Therefore it's advisable to avoid mixing ClonedPtr and SharedPtr, because it may lead to unexpected results when calls are made from different threads.
There are some predefined helper functions, which may be useful in some cases, by creating functors from them, with mkF. They can be used in compositions with existing functors or to simply pass them as arguments to standard algorithms (see the examples with mkF(identity<int>) in functorTstAlgorithms(), below, which prints a vector of int). These functions are located in <TemplMiscUtils.h>: There are also the null functors, which allow creating functors with a given signature but which don't do anything.
double f01(int x, char* p, double y) { return x + *p + y; }


struct TstStruct01
{
    int m() { return 7; }
    int cm() const { return 3; }

    const int cn;
    int n;
};


void functorTstCreation()
{
    cout << "======================= functorTstCreation() ===================================\n";
    // creating a functor from a global function
    Functor<double (int, char*, double)> fct1 (mkF(f01));

    // creating a functor from a value
    Functor<int ()> fct2 (mkF(5)); // constant 5
    Functor<long ()> fct2a (mkF(5L));
    cout << fct2() << " " << fct2a() << endl; // 5 5

    // creating a functor from a variable, showing that changing the variable changes the value of the functor
    int n (9);
    Functor<int ()> fct3 (mkF(n));
    cout << fct3() << endl; // 9
    n = 4; // changing the variable changes the value of the functor
    cout << fct3() << endl; // 4

    // creating a functor from a variable, showing all the combinations of const and reference
    string s ("abc");
    Functor<string ()> fct4 (mkF(s)); // return by value
    Functor<const string ()> fct4a (mkFC(s)); // return by const value
    Functor<string& ()> fct4b (mkFR(s)); // return by reference
    Functor<const string& ()> fct4c (mkFCR(s)); // return by const reference


    //----------------------------------------------------------------------------------

    // creating a functor from a method, taking a reference as the first param
    Functor<int (TstStruct01&)> fct5 (mkF(&TstStruct01::m)); // non-const method
    Functor<int (const TstStruct01&)> fct5a (mkF(&TstStruct01::cm)); // const method

    // creating a functor from a non-const data member
    Functor<int (TstStruct01&)> fct6 (mkF(&TstStruct01::n)); // non-const data member, return by value
    Functor<const int (const TstStruct01&)> fct6a (mkFC(&TstStruct01::n)); // non-const data member, return by const value
    Functor<int& (TstStruct01&)> fct6b (mkFR(&TstStruct01::n)); // non-const data member, return by reference
    Functor<const int& (const TstStruct01&)> fct6c (mkFCR(&TstStruct01::n)); // non-const data member, return by const reference

    // creating a functor from a const data member; like for the non-const, but the results are always const
    Functor<const int (TstStruct01&)> fct7 (mkF(&TstStruct01::cn)); // non-const data member, return by value
    Functor<const int (const TstStruct01&)> fct7a (mkFC(&TstStruct01::cn)); // non-const data member, return by const value
    Functor<const int& (TstStruct01&)> fct7b (mkFR(&TstStruct01::cn)); // non-const data member, return by reference
    Functor<const int& (const TstStruct01&)> fct7c (mkFCR(&TstStruct01::cn)); // non-const data member, return by const reference


    //----------------------------------------------------------------------------------

    // creating a functor from a method, taking a pointer as the first param
    Functor<int (TstStruct01*)> fct8 (mkFA(&TstStruct01::m)); // non-const method
    Functor<int (const TstStruct01*)> fct8a (mkFA(&TstStruct01::cm)); // const method

    // creating a functor from a non-const data member, taking a pointer
    Functor<int (TstStruct01*)> fct9 (mkFA(&TstStruct01::n)); // non-const data member, return by value
    Functor<const int (const TstStruct01*)> fct9a (mkFCA(&TstStruct01::n)); // non-const data member, return by const value
    Functor<int& (TstStruct01*)> fct9b (mkFRA(&TstStruct01::n)); // non-const data member, return by reference
    Functor<const int& (const TstStruct01*)> fct9c (mkFCRA(&TstStruct01::n)); // non-const data member, return by const reference

    // creating a functor from a const data member, taking a pointer
    Functor<const int (TstStruct01*)> fct10 (mkFA(&TstStruct01::cn)); // non-const data member, return by value
    Functor<const int (const TstStruct01*)> fct10a (mkFCA(&TstStruct01::cn)); // non-const data member, return by const value
    Functor<const int& (TstStruct01*)> fct10b (mkFRA(&TstStruct01::cn)); // non-const data member, return by reference
    Functor<const int& (const TstStruct01*)> fct10c (mkFCRA(&TstStruct01::cn)); // non-const data member, return by const reference


    //----------------------------------------------------------------------------------

    // creating a functor from helper functions
    Functor<const int (int)> fct11 (mkF(identity<const int>)); // !!! not "Functor<const int, const int>":
                                                // remember that "void f(const int);" is equivalent to "void f(int);"
    cout << fct11(15) << endl; // 15
    Functor<int& (int*)> fct12 (mkF(deref<int>));
    Functor<int (int*)> fct13 (mkF(derefV<int>));
    Functor<int* (int&)> fct14 (mkF(addr<int>));

    Functor<void ()> fct15 (mkF(nullFunctor0<void>));
    Functor<int (int)> fct16 (mkF(nullFunctor1<int, int>));

    //----------------------------------------------------------------------------------

    // creating named functors with specified sharing policy
    Functor<const int (int), SharedPtr> fct17 (mkF(identity<const int>)); // SharedPtr is the default anyway
    Functor<int (TstStruct01*), ClonedPtr> fct18 (mkFA(&TstStruct01::m));
    Functor<const string (), ClonedPtr> fct19 (mkFC(s)); 
    Functor<long (), ClonedPtr> fct20 (mkF(5L));
}
Operations
You can create another functor from an existing one by using "operations". One interesting thing about functor objects is that they are immutable; they don't change after they are created. The only thing you can do to a functor variable is to asssign it a new value; all the methods are const.
So there are many "operations" that look like they modify a functor, but what they are doing is creating and returning a new one.
The supported operations are:
Most operations create functors with the same number of arguments as the original, but these are the exceptions:
int f11(int x, char* p, int y) { return x + *p + y; }
char* f12(char& c) { return &c; }
int f13() { return 9; }

void functorTstOperations()
{
    cout << "======================= functorTstOperations() ===================================\n";
    char c (10);

    // a simple functor that returns "int" and takes 3 params (int, char*, int), representing the global function f11
    Functor<int (int, char*, int)> fct1 (mkF(f11));
    cout << fct1(4, &c, 7) << endl; // 4+10+7=21

    // fct2 is built by "composition on position 2", which effectively changes the type of the
    //    second argument from "char*" to "char&"
    // fct2(x, y, z) <=> fct1(x, f12(y), z) <=> fct1(x, &y, z)
    Functor<int (int, char&, int)> fct2 (fct1.comp<2>(mkF(f12)));
    cout << fct2(4, c, 7) << endl; // 4+10+7=21

    // by "composition on position 3" with mkF(f13), the third argument is effectively eliminated
    // fct2a(x, y) <=> fct1(x, y, f13())
    Functor<int (int, char*)> fct2a (fct1.comp<3>(mkF(f13)));
    cout << fct2a(4, &c) << endl; // 4+10+9=23

    // fct3 is built by "dereferencing the argument on position 2", so it behaves identically to fct2
    // fct3(x, y, z) <=> fct1(x, &y, z) <=> fct2(x, y, z)
    Functor<int (int, char&, int)> fct3 (fct1.deref<2>());
    cout << fct3(4, c, 7) << endl; // 4+10+7=21

    // by "dereferencing" the result of the functor created by mkF(f12),
    //    we really get the identity functor, returning what was passed to it
    // since fct4(c) returns a "char&", its result can be passed as the second argument to fct3
    Functor<char& (char&)> fct4 (mkF(f12).deref());
    cout << fct3(4, fct4(c), 7) << endl; // 4+10+7=21

    // by "taking the address of the argument on position 1" of fct4, that parameter becomes a pointer in fct5
    Functor<char& (char*)> fct5 (fct4.addr<1>());

    // by "taking the address of the result" of fct4, the result becomes a pointer in fct6
    Functor<char* (char&)> fct6 (fct4.addr());

    // by "binding on position 3", the third argument is eliminated and the result is the same as fct2a
    // fct7(x, y) <=> fct1(x, y, 9) <=> fct2a(x, y)
    Functor<int (int, char*)> fct7 (fct1.bind<3>(9));
    cout << fct7(4, &c) << endl; // 4+10+9=23

    // by "replacing the argument on position 3 with the one in position 1", the third argument is eliminated
    // fct8(x, y) <=> fct1(x, y, x)
    Functor<int (int, char*)> fct8 (fct1.del<3, 1>());
    cout << fct8(4, &c) << endl; // 4+10+4=18

    // by "applying the permutation <2, 3, 1>", the order of the arguments is changed
    // fct9(x, y, z) <=> fct1(y, z, x)
    Functor<int (char*, int, int)> fct9 (fct1.perm<2, 3, 1>());
    cout << fct9(&c, 4, 7) << endl; // 10+4+7=21

    // by "applying casting", static_cast is called for all arguments and for the result
    // fct10 is like fct1, with "int" cast to "char", so it overflows if passed arguments that are too big
    Functor<char (char, char*, char)> fct10 (fct1.cast<char, char, char*, char>());
    cout << (int)fct10(4, &c, 7) << endl; // 4+10+7=21
    cout << fct1(127, &c, 127) << endl; // 127+10+127=264;
    cout << (int)fct10(127, &c, 127) << endl; // 127+10+127=264; overflow (on most systems), so probably 8

}
Expressions (arithmetic, boolean, string)
As long as two functors return compatible types and take compatible arguments, it is possible to build expressions with them, using the following operators: "+(binary)", "-(binary)", "*(binary)", "/", "%", "<", ">", ">=", "<=", "==", "!=", "&&", "||", "&(binary)", "|", "^", "<<", ">>", "~", "!", "-(unary)", "+(unary)".
If both f1 and f2 have the signature <int (int)>, then f1 + f2 is a functor, which has the signature <int (int)> too and (f1 + f2)(a) returns f1(a) + f2(a), while f1 <= f2 has the signature <bool (int)> and (f1 <= f2)(a) returns f1(a) <= f2(a).
What happens if the functors involved in the expression are not of identical signatures? In a few words, the "expression functor" will be compilable and usable if it makes sense, and QuickFunctor tries really hard to do the "right thing". Roughly speaking, its result and parameters will be chosen in such a way as to avoid data loss by truncation. Another thing that is done is choosing the most derived class when the parameters on the same position are classes (or references or pointers to classes). For more details you can see the comments in CommonType.h and those in ApplyOp.h, but that's a difficult read; better look at the examples and do some experimentation.
I took the decision to allow expressions between functors with different number of parameters. For example, by adding a functor f1 with the signature <int (int)> to a functor f2 with the signature <int (int, int, int)>, the result is going to have the signature <int (int, int, int)>. The way the addition works is this: assuming that the parameters are called x, y and z, the result of (f1+f2)(x, y, z) will be f1(x) + f2(x, y, z). It's not completely right to allow this. However in some cases this makes a lot of sense, like when adding (or subtracting, comparing, ...) a functor with the signature <int (int)> to a literal constant or to a functor with the signature <int ()>. So this is allowed, until I'm presented with reasons good enough to forbid it. To determine the type of the parameters of the "expression functor", CommonParamType (from CommonType.h) is called as long as both functors have parameters in some position, and the types for the rest of the parameters are just copied from the remaining types of the functor with more parameters.
Another rather unusual thing is the ability to "add" functors that return void. Given two functors f1 and f2, if at least one of them returns void and their arguments are compatible, they can be "added", with the + operator. All this does is calling first the first functor, with whatever parameters it needs, and then calling the second functor; any results are ignored. The f1+f2 functor will return void. Being able to have additions (-, * or other operations are not allowed) with functors that return void is something experimental, which I feel might lead to something interesting but I don't currently have a very good reason for allowing it. There's assymetry there, because something can be added but not removed.
There's a special treatment for the << and >> operators. They are done in such a way that they work for both numbers and streams. See fct7 and fct7a in functorTstArithmExpr() for how would they work with streams, where it's possible to incorporate std::cout in a functor and print something at every call, without ostream being even in the signature of fct7a. Note that the functor for cout is created with mkFR, because we want to create a reference, not a copy.
Note that the header <FunctorExpressions.h> is needed for expressions, most likely along with <NumericCommonTypes.h> and/or <StringCommonTypes.h>.
int f21(int x) { return x + 10; }
int f22(short x) { return x * 3; }
int f23(int x, int y) { return x/y; }
string f24(const string& x) { return x + "#" + x; }
const string& f25(const string& x) { static string s; s = ">>" + x + "<<"; return s; } // not a good idea to have a "static", but it's just an example


void functorTstArithmExpr()
{
    cout << "======================= functorTstArithmExpr() ===================================\n";

    Functor<int (int)> fct1 (mkF(f21));
    Functor<int (short)> fct2 (mkF(f22));
    Functor<int (short)> fct3 (fct1 - fct2); // fct3(x) = (x + 10) - (x * 3)
    cout << fct3(4) << endl; // (4+10)-(4*3)=2

    Functor<int (short)> fct4 (mkF(f21) - mkF(f22)); // fct4(x) <=> fct(x)
    Functor<int (short)> fct5 (mkF(f21) - 2*mkF(f22) + 15); // fct4(x) = (x + 10) - 2*(x * 3) + 15
    cout << fct5(4) << endl; // (4+10)-2*(4*3)+15=5

    Functor<int (int, int)> fct6 (mkF(f21) - mkF(f23)); // fct6(x, y) = (x + 10) - (x / y)
    cout << fct6(8, 2) << endl; // (8+10)-(8/2)=14

    (mkFR(cout) << fct6 << "\n")(8, 2); // 14, as before, but the action of evaluatingthe whole functor does both the calculation and the printing
    Functor<ostream& (int, int)> fct7 (mkFR(cout) << fct6 << "\n"); // the corresponding named functor
    fct7(15, 3); // (15+10)-(15/3)=20 ; evaluating this also does the printing
    Functor<void (int, int)> fct7a (fct7.cast<void, int, int>());
    fct7a(15, 3); // (15+10)-(15/3)=20 ; evaluating this does the printing, like with fct7, but the signature has no reference to a stream

    cout << "---------- strings ---------" << endl;
    Functor<string (const string&)> fct8 (mkF(f24) + " added expr ptr");
    cout << fct8("WW") << endl; // "WW#WW added expr ptr"
    Functor<bool (string)> fct9 (mkF(identity<string>) == "str1");
    string a1 ("str1");
    cout << fct9(a1) << fct9("str1") << fct9("str2") << endl; // 110, meaning "true, true, false"

    Functor<string (const string&)> fct10 (mkF(f24) + " *** " + mkF(f25)); // note that the result is "string", even if f25 returns "const string&"
    cout << fct10("o") << endl; // "o#o *** >>o<<"
}


//----------------------- parameters of various members belong to derived classes ------------------

struct Base01
{
    int m1() { return 4; }
};

struct Der01 : public Base01
{
    Der01(int x1) : x(x1) {}
    Der01(int* p) : x(*p + 10) {}
    int x;
    int m2() const { return x; }
};

int f26(Base01* pb) { return pb->m1(); }
int f27(const Der01* pd) { return pd->m2(); }
int f28(int* p) { return *p; }
int f29(const Der01& d) { return d.m2() + 3; }

void functorTstArithmExprDer()
{
    cout << "====================== functorTstArithmExprDer() =================================\n";

    Functor<int (Der01*)> fct01 (mkF(f26) + mkF(f27) + mkFA(&Base01::m1)); // 4 + x->x + 4
    Der01 d (3);
    cout << fct01(&d) << endl; // 11

    Functor<int (int*)> fct02 (mkF(f28) * mkF(f29)); // *x * ((*x + 10) + 3)

    int x (2);
    int* p;
    CommonParamType<int*, const Der01&>::Type q (&x); // q is a "int*"
    p = q; // &x
    cout << fct02(p) << endl; // 30
}


//---------------------------- expressions with functors that return void --------------------------

void f210() { cout << "<inside f210>"; }
void f211() { cout << "<inside f211>"; }
int f212() { cout << "<inside f212>"; return 8; }
int f213(int x) { cout << "<inside f213; param: " << x << ">"; return 8; }

void functorTstVoidExpr()
{
    cout << "========================= functorTstVoidExpr() ===================================\n";

    Functor<void ()> fct1 (mkF(f210));
    Functor<void ()> fct2 (mkF(f211));
    Functor<int ()>  fct3 (mkF(f212));
    Functor<void ()> fct4 (fct1 + fct2);
    fct4(); cout << endl; // <inside f210><inside f211>
    fct4 += fct1;
    fct4(); cout << endl; // <inside f210><inside f211><inside f210>
    fct4 = fct1 + fct2 + fct3;
    fct4(); cout << endl; // <inside f210><inside f211><inside f212>
    fct4 += fct3;
    fct4(); cout << endl; // <inside f210><inside f211><inside f212><inside f212>
    Functor<void (int)> fct5 (fct4 + mkF(f213));
    fct5(20); cout << endl; // <inside f210><inside f211><inside f212><inside f212><inside f213; param: 20>
}
Usage with algorithms
Basically you can use them wherever a standard algorithm (like for_each, find_if, partition, ... ) takes a functor. They even have defined result_type, argument_type, first_argument_type and second_argument_type. A thing to notice is that if you have containers of (smart) pointers, you'll probably want to use the variants of mkF with the "A" suffix (see Creating functors, above), so the functors it creates take pointers too.
int f31(int x) { return x - 1000; }

struct Pers
{
    int m_id;
    string m_name;
    const string& getNameCst() const { return m_name; }
    const string& getName() { return m_name; }
    Pers(int id, string name) : m_id(id), m_name(name) {}
};


void functorTstAlgorithms()
{
    cout << "======================= functorTstAlgorithms() ===================================\n";

    cout << "------------------------------------------------------------------------------\n";
    cout << "### print vector<int>\n";
    vector<int> v1;
    v1.push_back(1000); v1.push_back(1002); v1.push_back(1005);
    for_each(v1.begin(), v1.end(), mkFR(cout) << " ## " << mkF(identity<int>)); //  ## 1000 ## 1002 ## 1005
    cout << endl;

    cout << "### print bitwise negation of vector<int>\n";
    for_each(v1.begin(), v1.end(), mkFR(cout) << " " << ~(mkF(identity<int>))); // bitwise negation:  -1001 -1003 -1006
    cout << endl;

    cout << "### print arithmetic negation of vector<int>\n";
    for_each(v1.begin(), v1.end(), mkFR(cout) << " " << -(mkF(identity<int>))); // arithmetic negation:  -1000 -1002 -1005
    cout << endl;

    cout << "### find x such that \"f31(x) > 1\"\n";
    vector<int>::iterator it0 (find_if(v1.begin(), v1.end(), mkF(f31) > 1));
    cout << *it0 << endl; // 1002

    cout << "### custom print of vector<Pers>\n";
    vector<Pers> v2;
    v2.push_back(Pers(10, "name p10")); v2.push_back(Pers(11, "name p11")); v2.push_back(Pers(100, "name p100"));
    for_each(v2.begin(), v2.end(), mkFR(cout) << " - " << mkF(&Pers::m_id) << " [" << mkF(&Pers::getName) << "]\n");

    cout << "### find first pers with id > 10 in vector<Pers>\n";
    vector<Pers>::iterator it21 (find_if(v2.begin(), v2.end(), mkF(&Pers::m_id) > 10));
    cout << it21->m_id << " " << it21->m_name << endl;

    cout << "### find first Pers whose bitwise negation is smaller than -20 in vector<Pers>\n";
    vector<Pers>::iterator it22 (find_if(v2.begin(), v2.end(), ~mkF(&Pers::m_id) < -20));
    cout << it22->m_id << " " << it22->m_name << endl;



    cout << "### custom print of vector<Pers*>\n";
    vector<Pers*> v3;
    v3.push_back(new Pers(10, "name p10")); v3.push_back(new Pers(11, "name p11")); v3.push_back(new Pers(100, "name p100"));
    for_each(v3.begin(), v3.end(), mkFR(cout) << " - " << mkFA(&Pers::m_id) << " [" << mkFA(&Pers::getName) << "]\n");
    // v3's elements will never be deallocated, but it's just a demo

    cout << "### find first pers with id > 10 in vector<Pers*>\n";
    vector<Pers*>::iterator it31 (find_if(v3.begin(), v3.end(), mkFA(&Pers::m_id) > 10));
    cout << (*it31)->m_id << " " << (*it31)->m_name << endl;

    cout << "### find first Pers whose bitwise negation is smaller than -20 in vector<Pers*>\n";
    vector<Pers*>::iterator it32 (find_if(v3.begin(), v3.end(), ~mkFA(&Pers::m_id) < -20));
    cout << (*it32)->m_id << " " << (*it32)->m_name << endl;
}
Assignment expressions
It is possible to use the various assignment operators: "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "<<=", ">>=". If there is a functor f1 with the signature <int (string, double)> and a functor f2 with the signature <int (string, double)> (or <int (string)>, <int ()> or even just an int), it is legal to have f1 += f2, or f1 += 42. This feature shouldn't be abused, especially inside loops, because of the way functor expressions are represented. An expression is always going to take more space than the functors used to make it. The results of those expressions are unnamed functors, and so new wrappers are going to be created for them by the named functors, while the original wrappers (if any) will continue to exist. So after "f1 += 3; f1 -=3;", f1 will return the same values as before these 2 assignments, but it will take additional space for an addition of 3 and a subtraction of 3. Also, the time taken to evaluate the functor will be longer. But sometimes these assignment expressions can really simplify things.
int f41(int x, int y) { return x + y; }
int f42(int x, int y) { return x - y; }
int f43(int x) { return 2*x; }

void functorTstAssgnExpr()
{
    cout << "======================= functorTstAssgnExpr() ====================================\n";
    Functor<int (int, int)> fct1 (mkF(&f41));
    cout << fct1(3, 6) << endl; // 9
    fct1 = mkF(&f42) + 5; // x - y + 5
    cout << fct1(3, 6) << endl; // 2

    Functor<int (int)> fct2 (mkF(&f43)); // 2 * x
    cout << fct2(16) << endl; // 32

    fct1 = fct1 + fct2; // 3*x - y + 5
    cout << "-------- 01 --------\n";
    cout << fct1(0, 0) << endl; // 5
    cout << fct1(1, 0) << endl; // 8
    cout << fct1(0, 1) << endl; // 4
    cout << fct1(1, 1) << endl; // 7

    cout << "-------- 02 --------\n";
    cout << fct1(3, 6) << endl; // 8
    cout << (fct1 + fct2)(2, 9) << endl; // 6

    fct1 = mkF(&f41);
    fct1 = fct1 << fct2; // (x + y) << (2*x) , = (x + y)*pow(2, 2*x)
    cout << "-------- 03 --------\n";
    cout << fct1(1, 1) << endl; // 8
    cout << fct1(1, 2) << endl; // 12
    cout << fct1(1, 3) << endl; // 16
    cout << fct1(2, 1) << endl; // 48
    cout << fct1(2, 2) << endl; // 64
    cout << fct1(2, 3) << endl; // 80
    cout << fct1(3, 1) << endl; // 256
    cout << fct1(3, 2) << endl; // 320
    cout << fct1(3, 3) << endl; // 384

    cout << "-------- 04 --------\n";
    fct1 = fct1 << 1; // ((x + y) << (2*x)) << 1 , = (x + y)*pow(2, 1 + 2*x)
    cout << fct1(2, 3) << endl; // 160

    fct1 >>= 1; // (((x + y) << (2*x)) << 1) >> 1, = (x + y) << (2*x) , = (x + y)*pow(2, 2*x)
    cout << fct1(2, 3) << endl; // 80
    fct1 -= 5; // (x + y)*pow(2, 2*x) - 5
    cout << fct1(2, 3) << endl; // 75

    fct1 -= fct2; // (x + y)*pow(2, 2*x) - 5 - 2*x
    cout << fct1(2, 3) << endl; // 71
    //??? ++fct1; - probably not

}
Casting
If you need to do a casting for the result or for the parameters of a functor, there are 2 options. One option is to use the cast operation described above, which does a static_cast on all the types involved. If that's not good enough, you can use mkF on the helper functions staticCast, dynamicCast, constCast, or reinterpretCast, and combine that with the initial functor through composition. To change the type of the result compose a cast function with the original functor (like in fct1); to change the type of a parameter compose the functor with the cast function (like fct2a, fct3a or fct4a).
These functions are located in TemplMiscUtils.h (which is included by, FullFunctor.h, so if you already have that you also have the cast functions).
If there's a need, the result of a functor can be cast to void, like in fct4b (where admittedly there wasn't such a great need).
struct Base51 { virtual ~Base51() {} };
struct Der51 : public Base51
{
    int x;
    Der51(int x1) : x(x1) {}
};

int f52(int& x) { return x + 3; }
int f53(const Der51& x) { return x.x; }
int f54(int x) { return 2*x; }


void functorTstCast()
{
    cout << "========================= functorTstCast() =======================================\n";

    int a (5);
    Functor<long ()> fct1 (mkF(reinterpretCast<long, int*>).o(mkF(&a)));
    cout << fct1() << endl; // address of "a" as an integer

    const int b (9);
    Functor<int (int&)> fct2 (mkF(f52));
    Functor<int (const int&)> fct2a (fct2.o(mkF(constCast<int&, const int&>)));
    cout << fct2a(b) << endl; // 12
    cout << mkF(f52).o(mkF(constCast<int&, const int&>)) (b) << endl; // 12, same as before but to point out that this can be done "on the fly"

    const Base51& c (Der51(7)); // so it's really a derived class object
    Functor<int (const Der51&)> fct3 (mkF(f53));
    Functor<int (const Base51&)> fct3a (fct3.o(mkF(dynamicCast<const Der51&, const Base51&>)));
    cout << fct3a(c) << endl; // 7

    double d (3.0);
    Functor<int (int)> fct4 (mkF(f54));
    Functor<int (double)> fct4a (fct4.o(mkF(staticCast<int, double>)));
    cout << fct4a(d) << endl; // 6
    Functor<void (double)> fct4b (fct4a.cast<void, double>()); // it is possible to cast the result from some type to "void"
    fct4b(1.2);
}
Null functors
If you have to work with an interface where you need to pass some kind of functor but in your particular case there is nothing useful that that functor could possibly do, you can create functors that "do nothing", by applying mkF to one of the null functor helpers: nullFunctor0<R> for functors without parameters, nullFunctor1<R, P1> for functors with 1 parameter, ... They return whatever the default constructor for the result returns (that is considered 0 for numeric and pointer types, which lack constructors) and completely ignore the arguments. They also work if the result is void. More formally, they are:
template <typename T> T nullFunctor0(), template <typename T, typename P1> T nullFunctor1(P1), ...
void functorTstNullFunctors()
{
    cout << "====================== functorTstNullFunctors() ==================================\n";

    // nothing
    Functor<long ()> fct1 (mkF(nullFunctor0<long>));
    cout << fct1() << endl; // 0
    Functor<void ()> fct2 (mkF(nullFunctor0<void>));
    fct2(); // no output
    Functor<int* (char)> fct3 (mkF(nullFunctor1<int*, char>));
    cout << fct3('q') << endl; // 0, the param doesn't matter
}
Expressions with a user type
If you want to introduce new classes that are supposed to participate in functor expressions with existing types, you should probably read the comments in CommonType.h and those in ApplyOp.h. Integration of types like Fraction or BigNumber with the existing numerical types isn't that difficult, but it may be hard to understand how to do it. Shortly, you must choose a (probably) new series for your type, call one of the DEFINE_TYPE_INFOXXX macros and call the DEFINE_SERIES_ENTRY macro. However, if your new type has operators but doesn't interact with other types, these macros are not needed, as seen below. Expressions of functors using these types can easily be created and used. The functor fct1 is created as an addition of two functors with the signature <IntWrapper6 (IntWrapper6)>. However an attempt to create an fct2 as a subtraction of such objects would fail, because IntWrapper6 doesn't define an operator-().
struct IntWrapper6
{
    int val;
    IntWrapper6(int x) : val(x) {}
    IntWrapper6 operator+(const IntWrapper6& o) { return IntWrapper6(val + o.val); }
};

IntWrapper6 f61(IntWrapper6 x) { return IntWrapper6(x.val); }
IntWrapper6 f62(IntWrapper6 x) { return IntWrapper6(x.val*2); }

void functorTstStandaloneExpr()
{
    cout << "==================== functorTstStandaloneExpr() ==================================\n";
    Functor<IntWrapper6 (IntWrapper6)> fct1 (mkF(f61) + mkF(f62));
    //Functor<IntWrapper6 (IntWrapper6)> fct2 (mkF(f61) - mkF(f62)); // error, no operator-() defined
    IntWrapper6 a (3);
    cout << fct1(a).val << endl; // 9
    cout << fct1(7).val << endl; // 21
}
Finding the signature of a functor
Most of the times when your code using functors doesn't compile, it's because some functors have a different signature than the one you'd expect. If mkF(f1) * mkFA(&C1::f2) doesn't compile, you should look at the signatures of the two functors involved (mkF(f1) and mkFA(&C1::f2)) and try to understand where the incompatibilities are. Or, assuming that that one compiles OK but mkF(f1) * mkFA(&C1::f2) + mkF(w) doesn't, you have to look at the signatures of mkF(f1) * mkFA(&C1::f2) and of mkF(w). While determining the signatures can be done in your mind in the simpler cases, an automated technique would always help.
Assuming that you have a functor expression called <your_expression> (which is just a placeholder, so you can substitute it with mkF(f1) * mkFA(&C1::f2) or anything else), here is a technique based on a compiler error that allows you to find the signature of <your_expression>.
Comment out everything that's not working and add the following line:
Functor<int (int, int, int)> tmpfct = <your_expression>;
Then try to compile. That should give an error message including a VFunctor3Impl (NOT VFunctor3ImplBase), which will allow you to determine the signature of your functor, because the first 4 template arguments of VFunctor3Impl indicate what the actual signature of the functor is (the "4" comes from here: first for result and next 3 for parameters). Note that if the functor has fewer than 3 parameters, VFunctor3Impl will have some arguments of the type pearl::FunctorNoType; they should be ignored. You can see an example of this in the function findSig(), in other_tests/FunctorExpressionsTst.cpp. To see the actual errors you'll have to uncomment the line with "#define SEE_COMP_SIG_ERR".
Well, this technique works with GCC 4.1. If you have a different compiler, it will hopefully give you enough information, including the details of VFunctor3Impl.)
Note that this assumed that functors can have at most 3 arguments (as is the default). If you generate the code of Functor.h and FunctorExpressions.h (see Other notes, below) for other number, you should also adjust the test type to include the maximum number of templates parameters (that would be Functor<int (int, int, int, int, int)> if the maximum number of arguments is 5, and you should look for a VFunctor5Impl).
Dealing with errors
When something is wrong and the compiler generates an error (or hundreds of errors), I noticed that those errors tend to be quite incomprehensible. Here is some advice on how to deal with them, based on what are you trying to do:
Another thing that might be of some help is a function called seeType(x) in <TypeManip.h>, which is supposed to generate a compiler error containing the type of x. With functors, that type will most likely be some obscure class in <Functor.h>, which the end user isn't supposed to know about. Still, taking a look and trying to get familiar with what's going on might offer a solution.
About the code
I expect the code to seem to many people like a potential winner in an "Obfuscated C++" contest. Some things may look quite weird (like the fact that there's only one base class for functors, regardless of the number of parameters, or having a template parameter that is never actually used), others plainly uncompilable, others ignore "good practices" (member functions that can easily be moved out of a class), but the code has changed a lot since when I started developing it and for most things that are there now there is a good reason that they are that way (or that's how it looks to me). Virtually everything was rewritten at least two or three times times, precisely to address some issue or another, so, while the design goals didn't change much, the implementation evolved into something quite different from what was there in the beggining, something that seems to address most of these issues.
Currently, few explanations are made about why the code is the way it is and how the trickier parts work. It's a lot of SFINAE (Substitution Failure Is Not An Error) and then some other things, like template metaprogramming (including code to compute the inverse of a permutation). I can try to explain some things that I've done here, if there's such a demand, but the main purpose of a library is to be used, for which it's more important that its interface is well designed and well documented, rather than its implementation being understandable to the casual user. (For one thing, it's usually quite difficult to me to understand what the code in some particular implementation of the STL is doing.)
It may seem strange that a class like Comp or FunctorExprBase have several operator()'s, with different number of parameters. However, one will have the signature equal to the functor's signature and will be the only one what will compile (and it will need arguments of the appropriate type). Trying to use one of the others or incompatible parameters will generate a compiler error.
The reason bind<n>() is a member function (as well as all the other operations) is that I find code that uses it much easier to read when dealing with chained calls, because it corresponds to an infix, rather than prefix notation. Compare
mkF(f1).bind<2>(38).deref<1>().addr().comp<2>(mkF(f2).bind<1>(7)) to
comp<2>(addr(deref<1>(bind<2>(mkF(f1), 38))), bind<1>(mkF(f2), 7))
While at the first glance they both seem inscrutable, actually in the first case you just go left-to-right to follow what kind of operations are applied, which is arguably easier for most people. In the second case you have to start in the middle and then go back. The initial version of QuickFunctor used global functions, but then I switched to member functions, because from my point of view they are easier to read (but I'm aware that some people have no trouble with a prefix notation).
The code provides the "strong exception guarantee" (see Herb Sutter - "Exceptional C++", page 38) to the extent that I remembered to think about it. In several places I noticed that my initial implementation was unnecessarily unsafe and with a few changes I think I made it safe. Nevertheless, I might have missed some parts, but I don't expect this to be a big issue because there are very few dynamic resource allocations and the objects are immutable. If you don't deal with named functors, I guess the "nothrow guarantee" applies. With unnamed functors, all that happens is creating objects on the stack. While you can obviously run out of stack space while doing this, that would trigger some OS-dependent behaviour (like sending a signal) and not throw an exception, anyway. Of course, functors mainly call functions that they are passed at construction, so if those are not safe it doesn't do much good that the functors themselves are.
A note about the usage of macros: It is recommended in many places to avoid using macros, for various reasons. Currently there are no "needed" macros in QuickFunctor. In the file CommonType.h there are several DEFINE_TYPE_INFO variants and a DEFINE_SERIES_ENTRY. They are used only to prevent some mistakes, and the code could have been written entirely without them (but more prone to bugs). The end user only has to deal with them when integrating new types with existing types that are used as functor results or parameters in functor expressions, and that is done only once for every new type, so it's quite minimal. I considered using some macros to shorten operation calls that are made very often (like ADDR1 for addr<1>()), but for now I decided to refrain from doing it.
As far as I can tell, the code conforms to the current C++ standard, but I'm not really an expert, so there's a chance that it compiles and works in my environment even though it shouldn't.
Looking at the source code
First of all, just because it's available, it doesn't mean that you have to look at it. It's probably better to just look at the documentation and examples.
The only file meant to be looked at is FunctorTst.cpp, although efforts were made for the non-generated header files to be readable, under certain circumstances.
I expect that trying to examine the code is going to be annoying for many people, partly for my naming conventions and indentation style, but perhaps more for the length of the lines. The thing is that that's how I like it, because it allows more information to be displayed on the screen (and I can actually handle it all). So I use a 1600x1200 screen resolution, with the IDE maximized and a font that displays 210 characters per line. The editor must support (soft) word wrapping for the comments to be readable. I use KDevelop, which has this feature and the added bonus that the continuation of the line starts in the same column as the beginning of the line, and not in column 1. Something to alleviate this issue might be using proportional fonts, but the comments would still generally be too long. My intention was to pass all the files through a beautifier/formatter before releasing them, to get everything to the 80 chars per line that everybody seems to love. Unfortunately, I couldn't find one. While there are some that claim to handle C++, those that I tried seem to actually be slightly modified C beautifiers, which know very little about templates. That's a big issue, as QuickFunctor is a template library, and templates are everywhere. As for the comments, I found that I change them so often that it's a nightmare to keep them properly formatted if I use line breaks inside paragraphs. There are perhaps editors that realign paragraphs inside comments, but I haven't looked into this. Maybe I'll switch to 80-char lines once things start to stabilize.
Another thing to keep in mind is that the files Functor.h and FunctorExpressions.h are generated (see Other notes, below), by default handling functors with up to 3 parameters.
If you still want to look at the source code, there's another thing to know, namely some labels inside comments:
A comparison to the standard
Here I try to make a comparison between QuickFunctor and the Standard Library. It might not be completely accurate, because I don't know the standard implementation very well (because I don't use it).
Operation Standard QuickFunctor
create functor from member function, taking a reference mem_fun_ref mkF
create functor from member function, taking a pointer mem_fun mkFA
create functor from global function with 1 or 2 parameters ptr_fun mkF
create functor from global function with 3 (or more) parameters N/A mkF
create functor from member data, global or local variables or constants N/A mkF, mkFR, mkFC, mkFCR, mkFA, mkFRA, mkFCA, mkFCRA
binding first argument bind1st bind<1>
binding second argument bind2nd bind<2>
binding third argument N/A bind<3>
logical negators for functors taking one or two arguments not1, not2 !
logical negators for functors taking 3 (or more) arguments N/A !
other unary operations for functors N/A ~, -, +
binary operations for functors N/A +, -, *, /, %, <, >, >=, <=, ==, !=, &&, ||, &, |, ^, <<, >>
assignment operations for functors N/A +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
other "transform" operations (besides binding and negation) N/A comp, deref, addr, deref<n>, addr<n>, perm, cast
helpers equal_to, not_equal_to, greater, greater_equal, less, less_equal, logical_and, logical_or, multiplies, divides, plus, minus, modulus identity, deref, derefV, addr, staticCast, dynamicCast, constCast, reinterpretCast, nullFunctor0(), nullFunctor1(P1), ...
named functors N/A Functor<R>, Functor<R, P1>, Functor<R, P1, P2>, Functor<R, P1, P2, P3>
I don't believe there's any way to "port" the car example to use only the Standard Library. By that I mean that you can write code that does the same thing, but you'll have to create new classes and/or functions. This is unlike Boost Lambda, where you can just substitute QuickFunctor calls with Boost calls. However, what's missing from the standard is "composition". So if you somehow add "composition" (write your own or get it from somewhere), then I guess you can also port the example to the Standard Library.
A comparison to the Boost Library
Well, before I started to work on QuickFunctor I took a look at Boost and my reactions were mixed. While it obviously could do many things, the way to achieve something seemed too complicated. The same stays true now, after I took a closer look (but maybe not close enough). Maybe it's just about getting used to it, but I think I managed to create a smaller and more coherent package from what you find in Boost in the Lambda and Function libraries, (well, there is related functionality in Bind and Mem_fn, but I believe that Lambda supercedes them, at least in the areas that have functionality similar to QuickFunctor). Anyway, the thing is that I don't know Boost well enough to make a "fair and balanced" comparison (even assuming that I can stay objective).
Functionally speaking, Boost has some features that are not present in QuickFunctor, like the equivalent of comparison of named pointers or all sorts of classes to perform loops, tests, exception catching and more in a functor that you're building (if_then(condition, then_part), if_then_else(condition, then_part, else_part), if_then_else_return(condition, then_part, else_part), while_loop(condition, body), ...). No doubt, there are quite a few more things that you're going to find in Boost without an equivalent in QuickFunctor. But to me it seems that it's hard to write quickly code that uses them correctly.
On the other hand, QuickFunctor comes with a lot of features, like a code generator that allows you to generate header files that handle functors with more than 3 parameters and, well, perhaps that's it. Or maybe not :
I feel a bit uneasy that some Boost functions will take whatever you throw at them and try to do "the right thing" (e.g. the fact that you can bind both a pointer and a regular variable to a functor taking a pointer, or that the declaration function<bool (Car&)> f1 = &Car::mpg; succeeds, despite mpg()'s returning an int, not a bool). But that's a matter of taste, I guess. I tend to favor a more strict type checking, one that forces you to explicitly make a "cast", if one is needed. Related to this, I feel that it's easier in QuickFunctor to control whether parameters are passed by value or by reference.
Another issue that I have with the Boost approach is that if the underscore is missing and you just have 1, 2 or 3 instead of _1, _2 or _3, in many cases the code will compile just fine.
I don't know how easy it is to determine the signature of a lambda expression. For QuickFunctor there is a "compiler error" - based method. I guess something along these lines would work with Boost too.
I don't know how the pointer handling policy introduced in QuickFunctor 0.8.1.0 compares to Boost. QuickFunctor' named functors internally use some "smart pointers", that can be told to share or clone existing objects during construction and assignments. This is done by providing a second template argument when specifying the type of a named pointer.
It seems that most of the things covered by QuickFunctor can be done somehow by Boost Lambda. It's just that to me the way QuickFunctor does things looks more natural and less error prone (I'm talking about the user code, the library implementation is a different story). I can't seem to get used to _1, _2 and _3 and to the fact that anything you might ever want to do with functors is done using bind().
Since QuickFunctor needed the SP1 version of MSVC 2005 to work and it wouldn't compile with the original version, it's going to have more portability issues than Boost Lambda.
I spent some time porting my car example to Boost. It didn't go very smoothly, but I got it working. At first I couldn't figure how to use the Lambda library so I had an implementation based on the Bind library. It had code looking like this:
//findCars(v, mkF(&Car::make) == "Toyota" && mkF(&Car::mpg) >= 25);
findCars(v, bind(logical_and<bool>(), 
    bind(equal_to<string>(), bind(&Car::make, _1), "Toyota"), 
    bind(greater_equal<int>(), bind(&Car::mpg, _1), 25)));
It didn't strike me as particularly pretty, and I was convinced that something better could be done. After digging some more through the documentation, I came up with a Lambda-based implementation. Here is where it differs from the QuickFunctor version (the QuickFunctor variant is commented out, above each line of Boost-specific code):
[...]

//#include <FullFunctor.h>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/function.hpp>

[...]
//using namespace pearl;
using namespace boost;
using namespace boost::lambda;

[...]
//void findCars(vector<Car>& v, const Functor<bool (Car&)>& test)
void findCars(vector<Car>& v, const function<bool (Car&)>& test) [...]

bool hasTdi(const string& s) [...]

void sampleUsage()
{
    vector<Car> v;
    [...]
    cout << "Cars that have at least 23 mpg\n";
    //findCars(v, mkF(&Car::mpg) >= 23);
    findCars(v, bind(&Car::mpg, _1) >= 23);

    cout << "Cars that have the mpg between 23 and 41\n";
    //findCars(v, mkF(&Car::mpg) >= 23 && mkF(&Car::mpg) <= 41);
    findCars(v, bind(&Car::mpg, _1) >= 23 && bind(&Car::mpg, _1) <= 41);

    cout << "Toyotas that have at least 25 mpg\n";
    //findCars(v, mkF(&Car::make) == "Toyota" && mkF(&Car::mpg) >= 25);
    findCars(v, bind(&Car::make, _1) == "Toyota" && bind(&Car::mpg, _1) >= 25);

    vector<Car>::iterator it;
    //it = find_if(v.begin(), v.end(), mkF(hasTdi).comp<1>(mkF(&Car::model)));
    ////  mkF(hasTdi).o(mkF(&Car::model)) is a shortcut for the test above
    it = find_if(v.begin(), v.end(), bind(hasTdi, bind(&Car::model, _1)));
    cout << "A car that has TDI: " << (*it) << endl;
}
Since I'm not very well acquainted with Boost, chances are that a better implementation exists, but this looks good enough to me. Please let me know if you can think of a better one.
To me, the QuickFunctor version looks (quite unsurprisingly) slightly better, in the sense that I see it as more expressive and easier to develop with and to understand (I think it's easier to understand what mkF does than to figure what bind and _1 will do in some cases). Probably it's the other way around for somebody who uses Boost frequently for this kind of things.
Anyway, the actual question for a fair comparison comes down to the learning curve, the time it takes to get your code to compile and to do what you want, as well as the features that real users actually use. It's probably irrelevant that QuickFunctor has permutations; most users are never going to use them, unless some kind of programming idiom becomes popular that could benefit from such a feature. Well, Boost Lambda also has permutations, as well as many other things, but that is of little importance if nobody uses them.
Of course, performance matters too. I didn't do any performance comparison, but I'm pretty sure that QuickFunctor will be fast enough, maybe after some tweaks.
Sure, nothing prevents you from using both libraries in your programs, but I probably wouldn't do such a thing in a new program; or maybe, if each has a very important feature that's missing from the other. But there is a lot of overlap.
A comparison to the TR1 Library
First of all, I don't have a good understanding of TR1, so you should double-check this. It seems to me that roughly TR1 copied from Boost the libraries Function, Bind and Mem_fn. Judging by this Dinkumware page, it seems that only they have anything resembling a full TR1 implementation. Anyway, I don't have a complete TR1, so I couldn't actually test what works. I'm inclined to believe that my first Boost implementation (the one using logical_and) or something close to it will work (you'll have to include the proper headers). Apparently you can't build expressions with the arithmetic operators.
Please let me know if something that I wrote here is inaccurate, so I can fix it.
Issues and open items
The code works fine for me but I didn't test everything and I might have missed some things, so some bugs might exist.
Open items:
The efficiency and compiler optimization areas need more looking at. From my point of view I think the compiler can make a lot of optimizations and in many cases what is a function calling another calling another can be translated into comparing two CPU registers. However, I'll have to look more into what optimizations are allowed by the standard and what optimizations are actually performed by real-world compilers. That might lead to changes in the internal structure of the library, but most likely not to interface changes.
To some extent QuickFunctor can be used to replace lambda functions, but what it can achieve from this point of view is rather limited, and language support for lambda functions would still be nice to have in the next standard. At some point I scribbled on a piece of paper something that seemed to allow loops and tests inside an expression used to create a functor, but I thought it just looked too weird. An important thing that was missing was "local variables", anyway. After releasing QuickFunctor I took a closer look at Boost's Lambda library and I noticed that what I had in mind was something similar to "if_then(condition, then_part), if_then_else(condition, then_part, else_part), if_then_else_return(condition, then_part, else_part), while_loop(condition, body), ..." from Boost.
For now I think I'd rather keep it simple and not provide such a thing, even though it looks cool. If you actually need this functionality you can just ignore QuickFunctor and revert to creating your own functor class with a good old operator() with all the loops and tests you need inside it. Or perhaps a better approach is to just create a new function (instead of a whole new global class) with those loops, and call mkF() for that function. This has the advantage that you don't need to create an external class (you know that you can declare classes inside functions but you can't pass them as template parameters, don't you?), so the code will be shorter.
Other notes
The version included in the downloaded package handles functors with up to 3 parameters, but that can go up indefinitely if you generate your own files for some other maximum number of parameters (so long as the compiler can handle them). The maximum number of parameters that was tested (with an older version) was 9, which went OK, but made the compiler work a lot. The limit of 3 seemed reasonable for what I normally do, but feedback from other users might make me change it. To generate other files, just compile and run the file generator/FctGenerator.cpp. Its first argument is the maximum number of arguments for functors and the second argument is the directory where the files Functor.h and FunctorExpressions.h should go. You must end the directory name with the path separator of your OS ("\" on Windows and "/" on most other systems). The code of FctGenerator.cpp is a complete mess, but it should work. It's only been tested on GCC 4.1 on 64-bit Linux, but it doesn't contain template tricks so I expect it to work on most other systems too. Replace the old files with the generated ones and your version should be now able to handle your new maximum number of functor parameters.
The main test file is main_tests/FunctorTst.cpp. The files located in other_tests are other various tests, which more or less resemble those in FunctorTst.cpp. They are provided for 2 purposes: one is to give additional usage examples and the other is to help determine if things didn't break after some changes were made to the library (they should still compile). Also, they contain some comments about why some things are in some way or another and indicate possible future directions.
Project status
Beta, I guess. Or is it pre-alpha? While I believe that the code quality itself is pretty good and I don't envision any revolutionary changes or significant additions (or even bug fixes), names might change, obscure features might be dropped (permutations) or others might be added. However, I'm quite confident that porting a program written with the current version to new versions will require little change besides some Search&Replace. I would normally keep the current names, but somebody might present strong reasons for name changes and only in that case there will actually be changes. Another thing is that maybe some more operations would be really useful but I didn't need them so far; so new operations may be added, but that shouldn't impact existing code.
I usually find very few bugs in the code that I considered I was roughly done with (even if I did not extensively check it / test it), but chances are that there are some bugs in QuickFunctor. And then there are the usual disagreements about code that does what it says but it should really say and do something else (or so some would think). And then there's also the chance that a last-minute small change that should have a very localized impact actually breaks more things. But at least the results of running the test files look good, so it's unlikely that such thing happened.
Release history
A list of releases can be found in this file.
Contact and support
If you think you found a bug or a design issue, please let me know. Or if you have some suggestions or comments. The address is ciobi [at] inbox.com. I started to get a lot of spam there, so to make sure that I don't delete a message by mistake, I would recommend using a subject line starting with "====================" or something like this, to make it stand out from the spam (usually the mail from unknown addresses goes to the "spam" folder).
You are also encouraged to use the SourceForge forums.
I also created a QuickFunctor blog. Initially it was intended for comments from users who wanted to post anonymous, because I thought that was not possible on SourceForge. After I figured out how to enable anonymous posting on SourceForge, I thought I should remove the blog, but then I changed my mind and I'm going to keep it for a while, to post there any news that I might have if they don't warrant a new release.

Have fun,
Ciobi