PDA

View Full Version : Functors [C++]


sans-hubris
06-09-2002, 09:50 AM
Allow me to make a proposal to you. Many languages allow you to nest functions within other functions, except for C/C++! Function nesting is such a cool feature, isn't it?

For example, in Scheme, you can do the following:

(define powers-seq
(lambda (power)
(lambda (x)
(letrec
((power-list
(lambda (x lst)
(if (zero? x)
lst
(power-list (- x 1)
(if (null? lst)
(cons 1 lst)
(cons (* power (car lst)) lst)))))))))))

(define power3 (powers-seq 3))
;Now I have an infinite sequence of the powers of three.

Would it not be nice to be able to do something like this in C/C++?

Well, we can do something like this in C++, but there is not much we can do about C, for now. In C++, we need to take advantage of operator overloading of C++ classes. More specifically, we need to overload the () operator. The idea is that we will have objects that behave like functions (which will now be referred to as functors), and since you can have other objects within functions, you can embed other functors.

class fooFunctor;
class barFunctor;

fooFunctor foo;
barFunctor bar;

class fooFunctor
{
public:
void operator() (int parm1, int parm2) //This should be the only public function.
{
bar(parm1+parm2, parm1*parm2);
}
};

class barFunctor
{
public:
void operator() (int parm1, int parm2)
{
cout << parm1 << " " << parm2 << endl;
}
};

int main(void)
{
foo(5,9);
return 0;
}

I'll leave the creation of a powers_seq functor as an exercise for you to do.

Flangazor
09-18-2003, 02:18 PM
You forgot to mention that you can also create classes locally to functions.

void blah()
{
class pajamajammyjam
{
public:
void operator() (std::ostream& os)
{
os << "Its a pajama jammy jam!" << std::endl;
}
};
pajamajammyjam(std::cout);
}

In this way, it is a bit inferior to the Lisp version in terms of syntax (so many tokens, such little to express).

*ponders* I don't have time to play now, but would this work? If not, how would you go about something similar?

void blah()
{
class foo;
foo* f;
if(some_bool)
{
class foo{std::ostream os;public: void do_junk(){/*snarf*/}};
f = new foo;
}
else
{
class foo{double xx; public: void do_junk(){/*?*/}};
f = new foo;
}
f->do_junk();
}


*update* I tried it and it doesn't compile.

Big Cheez
10-28-2003, 06:10 PM
//You do this.
void blah(){
//do stuff
}
void yada(){
blah();
}

DeBug
11-27-2003, 08:35 AM
void blah()
{
class foo;
foo* f;
if(some_bool)
{
class foo{std:stream os;public: void do_junk(){/*snarf*/}};
f = new foo;
}
else
{
class foo{double xx; public: void do_junk(){/*?*/}};
f = new foo;
}
f->do_junk();
}
Can not be compiled because at line f->do_junk()
function foo::do_junk is out of visibility

jemfinch
12-31-2003, 06:49 AM
Just as a note, C++ "functors" are completely different than functors in ML (which predate C++ "functors" by a significant amount).

Jeremy

junbiaobill
06-08-2005, 12:48 AM
*ponders* I don't have time to play now, but would this work? If not, how would you go about something similar?

void blah()
{
class foo;
foo* f;
if(some_bool)
{
class foo{std::ostream os;public: void do_junk(){/*snarf*/}};
f = new foo;
}
else
{
class foo{double xx; public: void do_junk(){/*?*/}};
f = new foo;
}
f->do_junk();
}


*update* I tried it and it doesn't compile.

code below will be compiled correctly.


#include<iostream>
using namespace std;

void blah(bool some_bool)
{
class base{public:virtual void do_junk()=0;};
base* f;
if(some_bool)
{
class foo:public base {public: void do_junk(){}};
f = new foo;
}
else
{
class foo :public base { double xx;public: void do_junk(){}};
f = new foo;
}
f->do_junk();
}

void main()
{
blah(1); //do nothing
}