Functor vs "classic'' class with method ?

Yesterday I was searching for functor whats is it etc. and I found this link
http://stackoverflow.com/questions/356950/c-functors-and-their-uses
where everybody are so satisfied with the answer. But I still don't get it.

According to the msot useful answer code:

1
2
3
4
5
6
7
8
9
10
11
12
13
  // this is a functor
struct add_x {
  add_x(int x) : x(x) {}
  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 


why just dont't write a method in class as :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

struct add_x {
	add_x(int x) : x(x) {}

	int add(int y) { 
		return x + y;
	}

private:
	int x;
};


//And call it like this
add_x addx(42); 
int i = addx.add(8); // here

assert(i == 50); // same result


So whats the purpose the functor against my code? Almost same amount of code, plus my code is more readable I think.

Thanks in advance.



Last edited on
I think one of the main benefits is that you can write template code that works for both functors and regular functions without doing anything special.

If you want to add 5 to each element in a vector you can use std::transform with a regular function as follows.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <vector>
#include <algorithm>

int add_5(int x)
{
	return x + 5;
}

int main()
{
	std::vector<int> vec {2, 7, 5, 10};
	
	std::transform(vec.begin(), vec.end(), vec.begin(), add_5);
	
	for (int i : vec)
	{
		std::cout << i << std::endl;
	}
}
7
12
10
15


If you don't want to hard code the value 5 you can use a functor.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <vector>
#include <algorithm>

struct add_x
{
	add_x(int x) : x(x) {}
	int operator()(int y) const { return x + y; }
private:
	int x;
};

int main()
{
	std::vector<int> vec {2, 7, 5, 10};
	
	std::cout << "Add how much? ";
	
	int n;
	std::cin >> n;
	
	std::transform(vec.begin(), vec.end(), vec.begin(), add_x(n));
	
	for (int i : vec)
	{
		std::cout << i << std::endl;
	}
}
Add how much? 5
7
12
10
15


A "class with method" is less general and can't be used as-is in situations like this. You say the functor is less readable but to me it looks a bit redundant with the word add repeated.
Last edited on
Another benefit of function objects like lambdas is that they may be 'defined' within other functions whereas a function cannot be defined within another function.
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>

int main()
{
    //int doubleInt(const int x){return 2*x;}
    //error: function-defnition is now allowed here ...

    auto doubleInt = [](const int x) -> int {return 2 * x;};

    std::cout << doubleInt(10) << "\n";//prints 20
}


https://msdn.microsoft.com/en-us/library/dd293608.aspx
Peter87 +1

The only real benefit is the support for polymorphism provided by the abstraction of the idea of a callable object.


> Another benefit of function objects like lambdas is that they may be 'defined' within other functions

Any object (not just a function object) may be an object of a local class type.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int main()  {

    struct add_x_one {

        explicit add_x_one(int x) : x(x) {} 
        int do_add( int y ) const { return x + y ; }// fine
        private: int x;
    };

    struct add_x_two {

        explicit add_x_two(int x) : x(x) {} 
        int do_add( int y ) const { return x + y ; } // also fine
        private: int x;
    };

    int v = 23 ;

    add_x_one x1(v) ;
    const int result1 = x1.do_add(456) ; // fine

    add_x_two x2(v) ;
    const int result2 = x2(456) ; // also fine
   
    assert( result1 == result2 && "both would yield the same result" ) ;
}


Topic archived. No new replies allowed.