CS253: Software Development with C++

Spring 2018

Functors

See this page as a slide show

CS253 Functors

A Method

Consider this class:

class Foo {
  public:
    int thrice(int n) { return n*3; }
};

Foo f;
cout << f.thrice(42) << '\n';
126

An operator function

Let’s use the ~ operator:

class Foo {
  public:
    const char *operator~() { return "hello"; }
};

Foo f;
cout << ~f << '\n';
hello

Another operator function

Let’s use the () operator, alias the “function call” operator:

class Foo {
  public:
    double operator()(int i, float f) { return i+f; }
};

Foo f;
cout << f(3,1.2) << '\n';
4.2

Sounds useless

😕

Another operator function

Let’s write a functor that returns its argument+1:

class BiggerBy1 {
  public:
    int operator()(int i) { return i+1; }
};

BiggerBy1 b;
cout << b(17) << '\n';
18

Another operator function

It’s easy to change that to increment by two, instead:

class BiggerBy2 {
  public:
    int operator()(int i) { return i+2; }
};

BiggerBy2 b;
cout << b(17) << '\n';
19

However, it would be tedious to have to write many such functors for all the different increment values we might want to use.

A stateful functor

Let’s give the functor a ctor argument:

class Bigger {
    const int increment;
  public:
    Bigger(int inc) : increment(inc) { }
    int operator()(int i) { return i+increment; }
};

Bigger b(4), c(12);
cout << b(17) << ' ' << b(100) << '\n'
     << b(1000) << ' ' << c(2000) << '\n';
21 104
1004 2012

The parentheses in b(4) are very different than the parentheses in b(17).

Another stateful functor

Another use of memory:

class Queue {
    int previous=0;
  public:
    int operator()(int n) {
        const auto save=previous;
        previous=n;
        return save;
    }
};

Queue q;
cout << q(12) << '\n';
cout << q(100) << '\n';
cout << q(42) << '\n';
0
12
100

Another stateful functor

Why does this fail?

class Queue {
    int previous=0;
  public:
    int operator()(int n) {
        const auto save=previous;
        previous=n;
        return save;
    }
};

Queue q;
cout << q(12) << '\n'
     << q(100) << '\n'
     << q(42) << '\n';
0
12
100

Even Queueier!

Multi-element queue:

class Queue {
    deque<int> store;
  public:
    Queue(int init_size) : store(init_size) { }
    int operator()(int n) {
        store.push_back(n);
        const auto f = store.front();
        store.pop_front();
        return f;
    }
};

Queue q(3);
for (int i=10; i<20; i++)
    cout << q(i) << '\n';
0
0
0
10
11
12
13
14
15
16

Or …

class Total {
    int sum=0;
  public:
    int operator()(int n) {
        return sum += n;
    }
};

Total t;
for (int i=0; i<=10; i++)
    cout << "Add " << i << " yielding " << t(i) << '\n';
Add 0 yielding 0
Add 1 yielding 1
Add 2 yielding 3
Add 3 yielding 6
Add 4 yielding 10
Add 5 yielding 15
Add 6 yielding 21
Add 7 yielding 28
Add 8 yielding 36
Add 9 yielding 45
Add 10 yielding 55

User: Guest

Check: HTML CSS
Edit History Source

Modified: 2018-04-24T16:52

Apply to CSU | Contact CSU | Disclaimer | Equal Opportunity
Colorado State University, Fort Collins, CO 80523 USA
© 2018 Colorado State University
CS Building