Consider this class:
class Foo { public: int thrice(int n) { return n*3; } }; Foo f; cout << f.thrice(42) << '\n';
126
int thrice(int n)
int
thrice
(int n)
Let’s use the ~
operator:
class Foo { public: const char *operator~() { return "hello"; } }; Foo f; cout << ~f << '\n';
hello
const char *operator~()
const char *
operator&
()
~Foo
.
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
double operator()(int i, float f)
double
operator()
(int i, float f)
😕
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
int operator()(int i)
int
operator()
(int i)
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.
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 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
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
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
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