What are C++ functors and their uses?
Asked Answered
T

14

1074

I keep hearing a lot about functors in C++. Can someone give me an overview as to what they are and in what cases they would be useful?

Torchbearer answered 10/12, 2008 at 17:47 Comment(4)
This subject has been covered in response to this question: https://mcmap.net/q/23223/-why-override-operator#317528Iridissa
It is used to create a closure in C++.Ventriloquy
Looking at answers below, if someone is wondering what does operator()(...) mean: it is overloading the the "function call" operator. It is simply operator overloading for the () operator. Don't mistake operator() with calling a function called operator, but see it as the usual operator overloading syntax.Moonwort
Very closely related: Why override operator()?Ethanol
A
1218

A functor is pretty much just a class which defines the operator(). That lets you create objects which "look like" a function:

// this is a functor
struct add_x {
  add_x(int val) : x(val) {}  // Constructor
  int operator()(int y) const { return x + y; }

private:
  int x;
};

// Now you can use it like this:
add_x add42(42); // create an instance of the functor class
int i = add42(8); // and "call" it
assert(i == 50); // and it added 42 to its argument

std::vector<int> in; // assume this contains a bunch of values)
std::vector<int> out(in.size());
// Pass a functor to std::transform, which calls the functor on every element 
// in the input sequence, and stores the result to the output sequence
std::transform(in.begin(), in.end(), out.begin(), add_x(1)); 
assert(out[i] == in[i] + 1); // for all i

There are a couple of nice things about functors. One is that unlike regular functions, they can contain state. The above example creates a function which adds 42 to whatever you give it. But that value 42 is not hardcoded, it was specified as a constructor argument when we created our functor instance. I could create another adder, which added 27, just by calling the constructor with a different value. This makes them nicely customizable.

As the last lines show, you often pass functors as arguments to other functions such as std::transform or the other standard library algorithms. You could do the same with a regular function pointer except, as I said above, functors can be "customized" because they contain state, making them more flexible (If I wanted to use a function pointer, I'd have to write a function which added exactly 1 to its argument. The functor is general, and adds whatever you initialized it with), and they are also potentially more efficient. In the above example, the compiler knows exactly which function std::transform should call. It should call add_x::operator(). That means it can inline that function call. And that makes it just as efficient as if I had manually called the function on each value of the vector.

If I had passed a function pointer instead, the compiler couldn't immediately see which function it points to, so unless it performs some fairly complex global optimizations, it'd have to dereference the pointer at runtime, and then make the call.

Apicella answered 10/12, 2008 at 17:58 Comment(21)
Can you explain this line, please std::transform(in.begin(), in.end(), out.begin(), add_x(1)); why you write there add_x, not the add42?Kristin
@Kristin Both would have worked (but the effect would have been different). If I'd used add42, I would have used the functor I created earlier, and added 42 to each value. With add_x(1) I create a new instance of the functor, one which only adds 1 to each value. It is simply to show that often, you instantiate the functor "on the fly", when you need it, rather than creating it first, and keeping it around before you actually use it for anything.Apicella
Can the functors have other member functions as well?Depend
@zadane of course. They just have to have the operator(), because that is what the caller uses to invoke it. What else the functor has of member functions, constructors, operators and member variables is completely up to you.Apicella
std::transform(in.begin(), in.end(), out.begin(), [](int &i){ i+=1;});Hydrant
@crl Shouldn't that be std::transform(in.begin(), in.end(), out.begin(), [](int i) { return i + 1; });?Endosmosis
"unlike regular functions, they can contain state" <- umm, regular functions can have static variables, so - they can contain state, albeit the semantics are a bit dodgy.Habiliment
@Apicella class which defines the operator() function isn't class but it still functor.Shit
@Shit In the parlance of functional programming, you're correct, a function is also a functor, but in the parlance of C++, the functor is specifically a class used as a function. The terminology was a bit abused early on, but the division is useful distinction and so persists today. If you start referring to functions as "functors" in a C++ context then you'll just confuse the conversation.Plaintive
Is it a class or an instance of the class? In most sources, add42 would be called a functor, not add_x (which is the class of the functor or just the functor class). I find that terminology consistent because functors are also called function objects, not function classes. Can you clarify this point?Vardar
so this is like in javascript when you have function makeadd(bynumber){ return function(x){ return x + bynumber; }}Dispensable
It puzzled me for quite a while that you named std::transform a function. It isn't, it's a template which looks like a function in your code thanks to template parameter deduction.Nosing
I love when people not only explain something but also give the motivation for using it. Thank you.Parish
@Habiliment functions can contain only one state unless you also pass the state (state itself or some value identifying state) as argument somehow.Nosing
The answer is good but it lacks some important data which is obvious to experienced programmers but not so much to newbies: 1) only function templates have advantage of making it obvious for compiler what function was used. 2) If function accepts std::function<whatever(whatever)> then the advantage of inlining is lost. --------- When I first read this answer years ago it left me in buggy state because of argument deduction which hidden the fact that you cannot pass any object to non-template function.Nosing
@EuriPinhollow when you pass arguments, e.g. std::transform(in.begin(), in.end(), out.begin(), add_x(1)), you have a function call. You are right that std::transform on it's own is not a function.Pattani
One more comment: it is still possible to inline function even if it is passed as function object value. BUT: compilers are able to inline calls even if function is passed by pointer, you do not need to have a template for that. It's just that with function template you cannot pass function defined at run time.Nosing
This is true. But with the new C++ 11 lambdas functors are pretty much dead. Now you may not need to create a whole class to have the function, instead have the function inlined in the method call. Lambdas are equally powerful in terms of both usage and performance.Verminous
@Verminous when you only have one operator(), sure. If you have a bunch of different operator()s sharing state then multiple lambdas are harder to get right than an explicit closure classPattani
What does std::transform(in.begin(), in.end(), out.begin(), add_x(1)); do at the first iteration, please?Electrotype
I'm specifically curious about the name functor, is this have anything to do with functors in cats theory? I've just heard this word from some friends, and I know nothing of it, nor am I interested in that direction -- just curious.Colophony
S
131

Little addition. You can use boost::function, to create functors from functions and methods, like this:

class Foo
{
public:
    void operator () (int i) { printf("Foo %d", i); }
};
void Bar(int i) { printf("Bar %d", i); }
Foo foo;
boost::function<void (int)> f(foo);//wrap functor
f(1);//prints "Foo 1"
boost::function<void (int)> b(&Bar);//wrap normal function
b(1);//prints "Bar 1"

and you can use boost::bind to add state to this functor

boost::function<void ()> f1 = boost::bind(foo, 2);
f1();//no more argument, function argument stored in f1
//and this print "Foo 2" (:
//and normal function
boost::function<void ()> b1 = boost::bind(&Bar, 2);
b1();// print "Bar 2"

and most useful, with boost::bind and boost::function you can create functor from class method, actually this is a delegate:

class SomeClass
{
    std::string state_;
public:
    SomeClass(const char* s) : state_(s) {}

    void method( std::string param )
    {
        std::cout << state_ << param << std::endl;
    }
};
SomeClass *inst = new SomeClass("Hi, i am ");
boost::function< void (std::string) > callback;
callback = boost::bind(&SomeClass::method, inst, _1);//create delegate
//_1 is a placeholder it holds plase for parameter
callback("useless");//prints "Hi, i am useless"

You can create list or vector of functors

std::list< boost::function<void (EventArg e)> > events;
//add some events
....
//call them
std::for_each(
        events.begin(), events.end(), 
        boost::bind( boost::apply<void>(), _1, e));

There is one problem with all this stuff, compiler error messages is not human readable :)

Secunderabad answered 10/12, 2008 at 19:15 Comment(3)
Shouldn't operator () be public in your first example since classes default to private?Hagioscope
maybe at some point this answer deserves an update, since now lambdas are the easiest way to get a functor from whateverBounder
int C++11 there are std::function and std::bindRothrock
I
130

A Functor is a object which acts like a function. Basically, a class which defines operator().

class MyFunctor
{
   public:
     int operator()(int x) { return x * 2;}
}

MyFunctor doubler;
int x = doubler(5);

The real advantage is that a functor can hold state.

class Matcher
{
   int target;
   public:
     Matcher(int m) : target(m) {}
     bool operator()(int x) { return x == target;}
}

Matcher Is5(5);

if (Is5(n))    // same as if (n == 5)
{ ....}
Isologous answered 10/12, 2008 at 17:58 Comment(7)
Just need to add that they can be used just like a function pointer.Scallion
@LokiAstari - For those that are new to the concept, that could be a bit misleading. Functors can be "used like", but not always "in place of" function pointers. For example, a function that takes a function pointer cannot take a functor in its place even if the functor has the same arguments and return value as the function pointer. But by and large when designing, functors are the preferred and theoretically "more modern" way to go.Beauvais
Why does the second one return int when it should return bool? This is C++, not C. When this answer was written, did bool not exist?Pard
@QPaysTaxes A typo I guess. I probably copy'n'pasted the code from the first example and forgot to change it. I've fixed it now.Isologous
Oh, that makes sense. Thanks for bearing with my pedantry :)Pard
What's the advantage using over bool Is5(int n) {return 5==n;}Roundelay
@Riasat If Matcher is in a library, defining Is5() is quite simple. ANd you can create Is7(), Is32() etc. Further, that's just an example. THe functor could be much more complicate.Isologous
K
69

Name "functor" has been traditionaly used in category theory long before C++ appeared on the scene. This has nothing to do with C++ concept of functor. It's better to use name function object instead of what we call "functor" in C++. This is how other programming languages call similar constructs.

Used instead of plain function:

Features:

  • Function object may have state
  • Function object fits into OOP (it behaves like every other object).

Cons:

  • Brings more complexity to the program.

Used instead of function pointer:

Features:

  • Function object often may be inlined

Cons:

  • Function object can not be swapped with other function object type during runtime (at least unless it extends some base class, which therefore gives some overhead)

Used instead of virtual function:

Features:

  • Function object (non-virtual) doesn't require vtable and runtime dispatching, thus it is more efficient in most cases

Cons:

  • Function object can not be swapped with other function object type during runtime (at least unless it extends some base class, which therefore gives some overhead)
Kati answered 21/11, 2009 at 16:59 Comment(6)
Can you explain these use case in real example? how can we use functors as polymorphism adn funtion pointer?Revisory
What actually does mean that a functor holds state?Blatherskite
thanks for pointing out that one needs a base class to have some kind of polymorphism. I just have the problem that I have to use a functor in the same place as a simple function pointer and the only way I found was to write a functor base class (as I cannot use C++11 stuff). Wasnt sure if this overhead makes sense until i read your answer.Bounder
@Erogol A functor is an object which happens to support the syntax foo(arguments). Therefore, it can contain variables; for example, if you had an update_password(string) function, you might want to keep track of how often that had happened; with a functor, that can be a private long time representing the timestamp it last happened. With a function pointer or plain function, you'd need to use a variable outside of its namespace, which is only directly related by documentation and usage, rather than by definition.lPard
⁺¹ for mentioning that the name have been made up for no reason. I've just been searching for what's the relation between mathematical (or functional if you want) functor and the one from C++.Generalship
Thanks for elaborating the misleading use of the word functor.Ventriloquy
D
47

Like others have mentioned, a functor is an object that acts like a function, i.e. it overloads the function call operator.

Functors are commonly used in STL algorithms. They are useful because they can hold state before and between function calls, like a closure in functional languages. For example, you could define a MultiplyBy functor that multiplies its argument by a specified amount:

class MultiplyBy {
private:
    int factor;

public:
    MultiplyBy(int x) : factor(x) {
    }

    int operator () (int other) const {
        return factor * other;
    }
};

Then you could pass a MultiplyBy object to an algorithm like std::transform:

int array[5] = {1, 2, 3, 4, 5};
std::transform(array, array + 5, array, MultiplyBy(3));
// Now, array is {3, 6, 9, 12, 15}

Another advantage of a functor over a pointer to a function is that the call can be inlined in more cases. If you passed a function pointer to transform, unless that call got inlined and the compiler knows that you always pass the same function to it, it can't inline the call through the pointer.

Donee answered 10/12, 2008 at 18:10 Comment(1)
I was looking exactly for this example because I have just seen it in a C++ course and I wasn't understanding it. Usually, we define an object of a class, which implements operator(), and pass it as an argument, a functor, to a function such as transform. However, in this case we are just constructing the object in the same call. Is that the only difference? That the functor goes out of scope and is destroyed once transform finishes? Thanks!Spradlin
A
46

For the newbies like me among us: after a little research I figured out what the code jalf posted did.

A functor is a class or struct object which can be "called" like a function. This is made possible by overloading the () operator. The () operator (not sure what its called) can take any number of arguments. Other operators only take two i.e. the + operator can only take two values (one on each side of the operator) and return whatever value you have overloaded it for. You can fit any number of arguments inside a () operator which is what gives it its flexibility.

To create a functor first you create your class. Then you create a constructor to the class with a parameter of your choice of type and name. This is followed in the same statement by an initializer list (which uses a single colon operator, something I was also new to) which constructs the class member objects with the previously declared parameter to the constructor. Then the () operator is overloaded. Finally you declare the private objects of the class or struct you have created.

My code (I found jalf's variable names confusing)

class myFunctor
{ 
    public:
        /* myFunctor is the constructor. parameterVar is the parameter passed to
           the constructor. : is the initializer list operator. myObject is the
           private member object of the myFunctor class. parameterVar is passed
           to the () operator which takes it and adds it to myObject in the
           overloaded () operator function. */
        myFunctor (int parameterVar) : myObject( parameterVar ) {}

        /* the "operator" word is a keyword which indicates this function is an 
           overloaded operator function. The () following this just tells the
           compiler that () is the operator being overloaded. Following that is
           the parameter for the overloaded operator. This parameter is actually
           the argument "parameterVar" passed by the constructor we just wrote.
           The last part of this statement is the overloaded operators body
           which adds the parameter passed to the member object. */
        int operator() (int myArgument) { return myObject + myArgument; }

    private: 
        int myObject; //Our private member object.
}; 

If any of this is inaccurate or just plain wrong feel free to correct me!

Abruption answered 4/1, 2013 at 20:6 Comment(2)
The () operator is called the function-call operator. I guess you could also call it the parentheses operator.Judicative
"This parameter is actually the argument "parameterVar" passed by the constructor we just wrote" Huh?Lohse
W
26

A functor is a higher-order function that applies a function to the parametrized(ie templated) types. It is a generalization of the map higher-order function. For example, we could define a functor for std::vector like this:

template<class F, class T, class U=decltype(std::declval<F>()(std::declval<T>()))>
std::vector<U> fmap(F f, const std::vector<T>& vec)
{
    std::vector<U> result;
    std::transform(vec.begin(), vec.end(), std::back_inserter(result), f);
    return result;
}

This function takes a std::vector<T> and returns std::vector<U> when given a function F that takes a T and returns a U. A functor doesn't have to be defined over container types, it can be defined for any templated type as well, including std::shared_ptr:

template<class F, class T, class U=decltype(std::declval<F>()(std::declval<T>()))>
std::shared_ptr<U> fmap(F f, const std::shared_ptr<T>& p)
{
    if (p == nullptr) return nullptr;
    else return std::shared_ptr<U>(new U(f(*p)));
}

Heres a simple example that converts the type to a double:

double to_double(int x)
{
    return x;
}

std::shared_ptr<int> i(new int(3));
std::shared_ptr<double> d = fmap(to_double, i);

std::vector<int> is = { 1, 2, 3 };
std::vector<double> ds = fmap(to_double, is);

There are two laws that functors should follow. The first is the identity law, which states that if the functor is given an identity function, it should be the same as applying the identity function to the type, that is fmap(identity, x) should be the same as identity(x):

struct identity_f
{
    template<class T>
    T operator()(T x) const
    {
        return x;
    }
};
identity_f identity = {};

std::vector<int> is = { 1, 2, 3 };
// These two statements should be equivalent.
// is1 should equal is2
std::vector<int> is1 = fmap(identity, is);
std::vector<int> is2 = identity(is);

The next law is the composition law, which states that if the functor is given a composition of two functions, it should be the same as applying the functor for the first function and then again for the second function. So, fmap(std::bind(f, std::bind(g, _1)), x) should be the same as fmap(f, fmap(g, x)):

double to_double(int x)
{
    return x;
}

struct foo
{
    double x;
};

foo to_foo(double x)
{
    foo r;
    r.x = x;
    return r;
}

std::vector<int> is = { 1, 2, 3 };
// These two statements should be equivalent.
// is1 should equal is2
std::vector<foo> is1 = fmap(std::bind(to_foo, std::bind(to_double, _1)), is);
std::vector<foo> is2 = fmap(to_foo, fmap(to_double, is));
Wardrobe answered 6/5, 2013 at 5:47 Comment(7)
Article arguing that functor should correctly be used for this meaning (see also en.wikipedia.org/wiki/Functor), and that using it for function objects is just sloppy: jackieokay.com/2017/01/26/functors.html It may be too late for that though, given the number of answers here that only consider the function object meaning.Irkutsk
This answer should be the one with >700 Upvotes. As someone how knows Haskell better than C++, the C++ lingua puzzled me all the times.Geisel
Category theory and C++? Is this Bartosz Milewski's secret SO account?Endosmosis
It might be helpful to summarize the functor laws in standard notation: fmap(id, x) = id(x) and fmap(f ◦ g, x) = fmap(f, fmap(g, x)).Endosmosis
@Geisel whilst functor also means this, C++ overloads the name to mean the same as "function object"Pattani
There is no mention of functor in the C++ standard. cppreference.com provides no definition of functor while it does provide a definition of FunctionObject with no mention of functor at all.Wardrobe
C++ and math terminology diverge in a lot of areas. This is neither undesirable nor wrong. E.g. "vector". Math concepts like "array", "sequence", "matrix" or "vector" have no equivalent in programming, because programming requires a concrete data type, which math is completely unconcerned with. In math you might talk about a sequence of numbers, but in programming this is meaningless. Are you talking about a list? a vector? a deque? The fact that some of these terms duplicate mathematical ones is fine. Even "function" does not have the mathematical meaning, which is why function object fails.Safeguard
R
9

Here's an actual situation where I was forced to use a Functor to solve my problem:

I have a set of functions (say, 20 of them), and they are all identical, except each calls a different specific function in 3 specific spots.

This is incredible waste, and code duplication. Normally I would just pass in a function pointer, and just call that in the 3 spots. (So the code only needs to appear once, instead of twenty times.)

But then I realized, in each case, the specific function required a completely different parameter profile! Sometimes 2 parameters, sometimes 5 parameters, etc.

Another solution would be to have a base class, where the specific function is an overridden method in a derived class. But do I really want to build all of this INHERITANCE, just so I can pass a function pointer????

SOLUTION: So what I did was, I made a wrapper class (a "Functor") which is able to call any of the functions I needed called. I set it up in advance (with its parameters, etc) and then I pass it in instead of a function pointer. Now the called code can trigger the Functor, without knowing what is happening on the inside. It can even call it multiple times (I needed it to call 3 times.)


That's it -- a practical example where a Functor turned out to be the obvious and easy solution, which allowed me to reduce code duplication from 20 functions to 1.

Rosabelle answered 26/12, 2011 at 6:54 Comment(2)
If your functor called different specific functions, and these other functions varied in the number of parameters they accept, does this mean your functor accepted a variable number of arguments for dispatching to these other functions?Tove
can you please explain the above scenario by quoting some part of code , i am new to c++ want to understand this concept..Molder
C
4

Like has been repeated, functors are classes that can be treated as functions (overload operator ()).

They are most useful for situations in which you need to associate some data with repeated or delayed calls to a function.

For example, a linked-list of functors could be used to implement a basic low-overhead synchronous coroutine system, a task dispatcher, or interruptable file parsing. Examples:

/* prints "this is a very simple and poorly used task queue" */
class Functor
{
public:
    std::string output;
    Functor(const std::string& out): output(out){}
    operator()() const
    {
        std::cout << output << " ";
    }
};

int main(int argc, char **argv)
{
    std::list<Functor> taskQueue;
    taskQueue.push_back(Functor("this"));
    taskQueue.push_back(Functor("is a"));
    taskQueue.push_back(Functor("very simple"));
    taskQueue.push_back(Functor("and poorly used"));
    taskQueue.push_back(Functor("task queue"));
    for(std::list<Functor>::iterator it = taskQueue.begin();
        it != taskQueue.end(); ++it)
    {
        *it();
    }
    return 0;
}

/* prints the value stored in "i", then asks you if you want to increment it */
int i;
bool should_increment;
int doSomeWork()
{
    std::cout << "i = " << i << std::endl;
    std::cout << "increment? (enter the number 1 to increment, 0 otherwise" << std::endl;
    std::cin >> should_increment;
    return 2;
}
void doSensitiveWork()
{
     ++i;
     should_increment = false;
}
class BaseCoroutine
{
public:
    BaseCoroutine(int stat): status(stat), waiting(false){}
    void operator()(){ status = perform(); }
    int getStatus() const { return status; }
protected:
    int status;
    bool waiting;
    virtual int perform() = 0;
    bool await_status(BaseCoroutine& other, int stat, int change)
    {
        if(!waiting)
        {
            waiting = true;
        }
        if(other.getStatus() == stat)
        {
            status = change;
            waiting = false;
        }
        return !waiting;
    }
}

class MyCoroutine1: public BaseCoroutine
{
public:
    MyCoroutine1(BaseCoroutine& other): BaseCoroutine(1), partner(other){}
protected:
    BaseCoroutine& partner;
    virtual int perform()
    {
        if(getStatus() == 1)
            return doSomeWork();
        if(getStatus() == 2)
        {
            if(await_status(partner, 1))
                return 1;
            else if(i == 100)
                return 0;
            else
                return 2;
        }
    }
};

class MyCoroutine2: public BaseCoroutine
{
public:
    MyCoroutine2(bool& work_signal): BaseCoroutine(1), ready(work_signal) {}
protected:
    bool& work_signal;
    virtual int perform()
    {
        if(i == 100)
            return 0;
        if(work_signal)
        {
            doSensitiveWork();
            return 2;
        }
        return 1;
    }
};

int main()
{
     std::list<BaseCoroutine* > coroutineList;
     MyCoroutine2 *incrementer = new MyCoroutine2(should_increment);
     MyCoroutine1 *printer = new MyCoroutine1(incrementer);

     while(coroutineList.size())
     {
         for(std::list<BaseCoroutine *>::iterator it = coroutineList.begin();
             it != coroutineList.end(); ++it)
         {
             *it();
             if(*it.getStatus() == 0)
             {
                 coroutineList.erase(it);
             }
         }
     }
     delete printer;
     delete incrementer;
     return 0;
}

Of course, these examples aren't that useful in themselves. They only show how functors can be useful, the functors themselves are very basic and inflexible and this makes them less useful than, for example, what boost provides.

Chauvin answered 8/2, 2014 at 5:26 Comment(0)
D
3

Except for used in callback, C++ functors can also help to provide a Matlab liking access style to a matrix class. There is a example.

Deductive answered 7/3, 2012 at 7:3 Comment(1)
This (the matrix example) is plain use of operator() but not making use of function object properties.Tamayo
S
2

Functors are used in gtkmm to connect some GUI button to an actual C++ function or method.


If you use the pthread library to make your app multithreaded, Functors can help you.
To start a thread, one of the arguments of the pthread_create(..) is the function pointer to be executed on his own thread.
But there's one inconvenience. This pointer can't be a pointer to a method, unless it's a static method, or unless you specify it's class, like class::method. And another thing, the interface of your method can only be:

void* method(void* something)

So you can't run (in a simple obvious way), methods from your class in a thread without doing something extra.

A very good way of dealing with threads in C++, is creating your own Thread class. If you wanted to run methods from MyClass class, what I did was, transform those methods into Functor derived classes.

Also, the Thread class has this method: static void* startThread(void* arg)
A pointer to this method will be used as an argument to call pthread_create(..). And what startThread(..) should receive in arg is a void* casted reference to an instance in heap of any Functor derived class, which will be casted back to Functor* when executed, and then called it's run() method.

Spiv answered 6/10, 2011 at 4:44 Comment(1)
Got an example?Mirtamirth
L
2

A big advantage of implementing functions as functors is that they can maintain and reuse state between calls. For example, many dynamic programming algorithms, like the Wagner-Fischer algorithm for calculating the Levenshtein distance between strings, work by filling in a large table of results. It's very inefficient to allocate this table every time the function is called, so implementing the function as a functor and making the table a member variable can greatly improve performance.

Below is an example of implementing the Wagner-Fischer algorithm as a functor. Notice how the table is allocated in the constructor, and then reused in operator(), with resizing as necessary.

#include <string>
#include <vector>
#include <algorithm>

template <typename T>
T min3(const T& a, const T& b, const T& c)
{
   return std::min(std::min(a, b), c);
}

class levenshtein_distance 
{
    mutable std::vector<std::vector<unsigned int> > matrix_;

public:
    explicit levenshtein_distance(size_t initial_size = 8)
        : matrix_(initial_size, std::vector<unsigned int>(initial_size))
    {
    }

    unsigned int operator()(const std::string& s, const std::string& t) const
    {
        const size_t m = s.size();
        const size_t n = t.size();
        // The distance between a string and the empty string is the string's length
        if (m == 0) {
            return n;
        }
        if (n == 0) {
            return m;
        }
        // Size the matrix as necessary
        if (matrix_.size() < m + 1) {
            matrix_.resize(m + 1, matrix_[0]);
        }
        if (matrix_[0].size() < n + 1) {
            for (auto& mat : matrix_) {
                mat.resize(n + 1);
            }
        }
        // The top row and left column are prefixes that can be reached by
        // insertions and deletions alone
        unsigned int i, j;
        for (i = 1;  i <= m; ++i) {
            matrix_[i][0] = i;
        }
        for (j = 1; j <= n; ++j) {
            matrix_[0][j] = j;
        }
        // Fill in the rest of the matrix
        for (j = 1; j <= n; ++j) {
            for (i = 1; i <= m; ++i) {
                unsigned int substitution_cost = s[i - 1] == t[j - 1] ? 0 : 1;
                matrix_[i][j] =
                    min3(matrix_[i - 1][j] + 1,                 // Deletion
                    matrix_[i][j - 1] + 1,                      // Insertion
                    matrix_[i - 1][j - 1] + substitution_cost); // Substitution
            }
        }
        return matrix_[m][n];
    }
};
Lothair answered 15/1, 2017 at 10:51 Comment(0)
D
1

To add on, I have used function objects to fit an existing legacy method to the command pattern; (only place where the beauty of OO paradigm true OCP I felt ); Also adding here the related function adapter pattern.

Suppose your method has the signature:

int CTask::ThreeParameterTask(int par1, int par2, int par3)

We will see how we can fit it for the Command pattern - for this, first, you have to write a member function adapter so that it can be called as a function object.

Note - this is ugly, and may be you can use the Boost bind helpers etc., but if you can't or don't want to, this is one way.

// a template class for converting a member function of the type int        function(int,int,int)
//to be called as a function object
template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
class mem_fun3_t
{
  public:
explicit mem_fun3_t(_Ret (_Class::*_Pm)(_arg1,_arg2,_arg3))
    :m_Ptr(_Pm) //okay here we store the member function pointer for later use
    {}

//this operator call comes from the bind method
_Ret operator()(_Class *_P, _arg1 arg1, _arg2 arg2, _arg3 arg3) const
{
    return ((_P->*m_Ptr)(arg1,arg2,arg3));
}
private:
_Ret (_Class::*m_Ptr)(_arg1,_arg2,_arg3);// method pointer signature
};

Also, we need a helper method mem_fun3 for the above class to aid in calling.

template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
mem_fun3_t<_Ret,_Class,_arg1,_arg2,_arg3> mem_fun3 ( _Ret (_Class::*_Pm)          (_arg1,_arg2,_arg3) )
{
  return (mem_fun3_t<_Ret,_Class,_arg1,_arg2,_arg3>(_Pm));
}

Now, in order to bind the parameters, we have to write a binder function. So, here it goes:

template<typename _Func,typename _Ptr,typename _arg1,typename _arg2,typename _arg3>
class binder3
{
public:
//This is the constructor that does the binding part
binder3(_Func fn,_Ptr ptr,_arg1 i,_arg2 j,_arg3 k)
    :m_ptr(ptr),m_fn(fn),m1(i),m2(j),m3(k){}

 //and this is the function object 
 void operator()() const
 {
        m_fn(m_ptr,m1,m2,m3);//that calls the operator
    }
private:
    _Ptr m_ptr;
    _Func m_fn;
    _arg1 m1; _arg2 m2; _arg3 m3;
};

And, a helper function to use the binder3 class - bind3:

//a helper function to call binder3
template <typename _Func, typename _P1,typename _arg1,typename _arg2,typename _arg3>
binder3<_Func, _P1, _arg1, _arg2, _arg3> bind3(_Func func, _P1 p1,_arg1 i,_arg2 j,_arg3 k)
{
    return binder3<_Func, _P1, _arg1, _arg2, _arg3> (func, p1,i,j,k);
}

Now, we have to use this with the Command class; use the following typedef:

typedef binder3<mem_fun3_t<int,T,int,int,int> ,T* ,int,int,int> F3;
//and change the signature of the ctor
//just to illustrate the usage with a method signature taking more than one parameter
explicit Command(T* pObj,F3* p_method,long timeout,const char* key,
long priority = PRIO_NORMAL ):
m_objptr(pObj),m_timeout(timeout),m_key(key),m_value(priority),method1(0),method0(0),
method(0)
{
    method3 = p_method;
}

Here is how you call it:

F3 f3 = PluginThreadPool::bind3( PluginThreadPool::mem_fun3( 
      &CTask::ThreeParameterTask), task1,2122,23 );

Note: f3(); will call the method task1->ThreeParameterTask(21,22,23);.

The full context of this pattern at the following link

Doerrer answered 28/1, 2013 at 6:50 Comment(0)
D
1

Functor can also be used to simulate defining a local function within a function. Refer to the question and another.

But a local functor can not access outside auto variables. The lambda (C++11) function is a better solution.

Deductive answered 20/2, 2014 at 3:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.