From: kriss@roll.ibp.fr (Christophe GROSJEAN)
Subject: Re: C++ already *has* nested functions SO WHAT'S THE BEEF?
Reply-To: grosjean@masi.ibp.fr
Organization: Laboratoire MASI, Paris, France.
Date: Thu, 24 Dec 1992 11:38:25 GMT

The following code shows another way of simulating nested functions.
That's what I use right now, waiting for the removing of this restriction.

I've read that GNU support nested functions, the compiler I use right know
(G++ 2.3.2) does not seem to do it. Which version does it ?

Sample (should say simple) code follow-up, with context. Use of templates is not
relevant to the nested function problem.

The syntax could be *much* simplified using macros. But stantard macro preprocessors
are not powerful enough.

First, anybody thought of removing the comma-as-separator restriction
in the preprocessor in order you can choose the right one ?
I had much trouble with that using macros with multi-arguments templated classes. 'cause of that.

Second, overloading should be extended to macros in C++, seems homogeneous, and
usefull.

Third, in my case, what I would need is context vars, stacking vars in a first macro then
using them in a second one, kind of parenthesing macros.

--------- code follows -------------

#include <iostream.h>
#define TRUE 1
#define FALSE 0

template<class R, class T>
class Func1
{
	public:
	virtual R call(T o1) = 0;
};

void * ONULL = NULL;

template<class DATA>
class List
{
	public:
	List(void) {init();}
	List(DATA o1){ init(); add(o1);}
	List(DATA o1, DATA o2){init(); add(o1); add(o2);}
	List(DATA o1, DATA o2, DATA o3){
		init(); add(o1); add(o2); add(o3);}
	List(DATA o1, DATA o2, DATA o3, DATA o4){
		init(); add(o1); add(o2); add(o3); add(o4);}
	void add(DATA o1){
		Link * tmp = new Link;
		tmp->next = head;
		tmp->data = o1;
		head = tmp;
	}
	void addAll(List<DATA> & c1) {
		class p : public Func1<void,DATA> {
			public:
			p(List<DATA> & c) : c(c) {}
			void call(DATA i) {c.add(i);}
			List<DATA> & c;
		} p(*this);
		c1.all(p);
	}
	void all(Func1<void,DATA> & p){
		Link * tmp;
		for(tmp=head;tmp != NULL;tmp=tmp->next)
			p.call(tmp->data);
	}
	DATA & any(Func1<int,DATA> & t){
		Link * tmp;
		for(tmp=head;tmp != NULL;tmp=tmp->next)
			if (t.call(tmp->data))
				return tmp->data;
		error = 1;
		return (DATA &)ONULL;
	}
	void unlink_any(Func1<int, DATA> & t){
		if (head == NULL){error = 1;return;}
		else{
			Link * tmp = head;
			if (t.call(tmp->data)){
				head = tmp->next;
				delete tmp;
				return;
			}
			else {
				Link * tmp2;
				for (tmp2 = tmp->next; tmp2 != NULL;tmp2=(tmp=tmp2)->next)
					if (t.call(tmp2->data)){
						tmp->next = tmp2->next;
						delete tmp2;
						return;
					}
			}
		}
		error = 1;
		return;
	}
	void unlink_all(Func1<int, DATA> & t){
		Link * tmp;
		Link * tmp2;
		tmp = head;
		head = NULL;
		while(tmp != NULL){
			tmp2 = tmp;
			tmp = tmp->next;
			if (t.call(tmp2->data))
			{
				delete tmp2;
			}
		{
			tmp2->next = head;
			head = tmp2;
		}
		}
		reverse();
	}

	int includes(Func1<int, DATA> & t){
		Link * tmp;
		for(tmp=head;tmp != NULL;tmp=tmp->next)
			if (t.call(tmp->data))
				return TRUE;
		return FALSE;
	}

	int occurencesOf(Func1<int, DATA> & t)
	{
		int nb = 0;
		for(Link * tmp=head;tmp != NULL;tmp=tmp->next)
			if( t.call(tmp->data)) nb++;
		return nb;
	}
	
 private:
	void init(void) { head = (Link *)NULL;}
	void reverse(){
		Link * tmp;
		Link * tmp2;
		tmp = head;
		head = NULL;
		while(tmp != NULL){
			tmp2 = tmp->next;
			tmp->next = head;
			head = tmp;
			tmp = tmp2;
		}
	}
	struct Link
	{
		Link * next;
		DATA data;
	} * head;
	int error;
 };

int main()
{
	class pint : public Func1<void,int>
	{
		public:
		pint(void) {}
		void call(int d) { cout << d << " "; }
	} pint;
	class pchar : public Func1<void,char>
	{
		public:
		pchar(void) {}
		void call(char d) { cout << d << " "; }
	} pchar;

	
	class t1 : public Func1<int,int>
	{
		public:
		t1(void) {}
		int call(int d) {return (d>=200);}
	} t1;
	
	int toto = 120;
	
// Function reading context variable toto (value a this point)
	class t2 : public Func1<int,int>
	{
		public:
		t2(int toto) : toto(toto) {}
		int call(int d) {return (d > toto);}
		int toto;
	} t2(toto);
	
	// Function using context variable toto (whatever value)
	class t3 : public Func1<int,int>
	{
		public:
		t3(int & toto) : toto(toto) {}
		int call(int d) {return (d <= toto);}
		int & toto;
	} t3(toto);
	
	// Function modifying context variable max
	int max;
	class getmax : public Func1<void, int>
	{
		public:
		getmax(int & max) : max(max) {}
		void call(int d) { max = (max > d)?max:d; }
		int & max;
	} getmax(max);
	
	List<char> L3('A','B','C');
	List<int> L1(100,120,130), L2(200);
	L1.add(110); L2.add(210);
	L1.addAll(L2); L1.add(140); L1.add(150); L1.add(160);
	cout << "List L1 : "; L1.all(pint); cout << "\n";
	cout << "List L2 : "; L2.all(pint); cout << "\n";
	cout << "List L3 : "; L3.all(pchar); cout << "\n";
	toto = 140;
	cout << "First elt of L1 veryfying elt >= 200 : " << L1.any(t1) << "\n";
	cout << "First elt of L1 veryfying elt > toto (120) : " << L1.any(t2) << "\n";
	cout << "First elt of L1 veryfying elt <= toto (now=140) : " << L1.any(t3) << "\n";
	L1.all(getmax);
	cout << "Max elt of L1 : " << max << "\n";
	
	return 0;
}
-------- end of code --------
Newsgroups: comp.std.c++