Google Groups unterstützt keine neuen Usenet-Beiträge oder ‑Abos mehr. Bisherige Inhalte sind weiterhin sichtbar.

define

0 Aufrufe
Direkt zur ersten ungelesenen Nachricht

Sebastian Pfützner

ungelesen,
23.01.2001, 11:46:5023.01.01
an
kurze Frage: wie macht man #define Anweisungen über mehrere Zeilen?
--
Sebastian Pfützner
ICQ-ID: 39965036

[ FAQ : http://www.voyager.prima.de/cpp/ ]
[ Moderation : mailto:voyag...@bud.prima.de ]

Martin Winkler

ungelesen,
23.01.2001, 12:35:0523.01.01
an

Sebastian Pfützner schrieb in Nachricht
<94kck7$lob$01$1...@news.t-online.com>...

>kurze Frage: wie macht man #define Anweisungen über mehrere Zeilen?

Kurze Antwort:
Man setzt ans Zeilenende einen Backslash (\) und sagt dem Präprozessor
damit, daß die (logische) Zeile in der nächsten Zeile fortgesetzt wird.

#define BEISPIEL cout \
<< \
"Text" \
;

Gruß Martin

Dietmar Kuehl

ungelesen,
23.01.2001, 12:58:1623.01.01
an
Hi,
Sebastian Pfützner (ki...@killerbastl.de) wrote:
: kurze Frage: wie macht man #define Anweisungen über mehrere Zeilen?

Garnicht: Wenn man sowas braucht macht man was falsch! In C++ gibt es
keine Platz fuer Makros, die mehrere Zeilen brauchen!

Fuer C Kompatibilitaet kann man ein Backslash '\' am Ende der Zeile
verwenden, um auf der naechsten Zeile weitermachen zu koennen. Aber wie
gesagt, fuer C++ Programme gibt es keinen Grund, sowas machen zu
wollen!
--
<mailto:dietma...@yahoo.com> <http://www.dietmar-kuehl.de/>
Phaidros eaSE - Easy Software Engineering: <http://www.phaidros.com/>

Stefan Reuther

ungelesen,
24.01.2001, 10:07:1124.01.01
an
Hallo,

Dietmar Kuehl <ku...@ramsen.informatik.uni-konstanz.de> wrote:
> Hi,
> Sebastian Pfützner (ki...@killerbastl.de) wrote:
> : kurze Frage: wie macht man #define Anweisungen über mehrere Zeilen?

> Garnicht: Wenn man sowas braucht macht man was falsch! In C++ gibt es
> keine Platz fuer Makros, die mehrere Zeilen brauchen!

Da gehe ich so pauschal nicht mit. Jedenfalls nutze ich
Mehrzeilen-Makros gerne mal, um mir (quasi) varargs-Templates
zu simulieren. Also z.B. sowas:
#define _ ,
#define DECLARE(NAME, ARGDECL, CALL) \
class NAME { \
void (*func)(ARGDECL); \
public: \
NAME(void (*afunc)(ARGDECL)) : func(afunc) { } \
void call(ARGDECL) { func(CALL); } \
};

template<class A> DECLARE(func_ptr1, A a, a)
template<class A, class B> DECLARE(func_ptr2, A a _ B b, a _ b)
usw. bis z.B. 6 Argumenten.
#undef _
#undef DECLARE

In leichter Variation verwende ich sowas gerade zur Implementation
von Closures. So richtig prall finde ich das zwar auch nicht,
aber IMHO besser, als denselben Code z.B. 6x hinzuschreiben.
Ich fand's zumindest praktisch, neulich einen Bug nur einmal
korrigieren zu müssen und nicht 6x.

Wer eine bessere Möglichkeit kennt, immer her damit. Ich würde
ja etwas der Form `template<class A ...>' bevorzugen, aber das
geht leider nicht :-(


Stefan

Sebastian Moleski (SurakWare)

ungelesen,
24.01.2001, 10:36:3924.01.01
an
"Stefan Reuther" <sr...@inf.tu-dresden.de>:

> In leichter Variation verwende ich sowas gerade zur Implementation
> von Closures. So richtig prall finde ich das zwar auch nicht,
> aber IMHO besser, als denselben Code z.B. 6x hinzuschreiben.
> Ich fand's zumindest praktisch, neulich einen Bug nur einmal
> korrigieren zu müssen und nicht 6x.
>
> Wer eine bessere Möglichkeit kennt, immer her damit. Ich würde
> ja etwas der Form `template<class A ...>' bevorzugen, aber das
> geht leider nicht :-(

Ich hab mal ein closure template geschrieben, das mit bis zu vier oder fünf
Argumenten funktioniert und ohne Makros auskommt. Schreib mir, wenn Du es
haben willst.

sm

Roland Jakobs

ungelesen,
24.01.2001, 13:38:3224.01.01
an

Dietmar Kuehl schrieb:

>
> Garnicht: Wenn man sowas braucht macht man was falsch! In C++ gibt es
> keine Platz fuer Makros, die mehrere Zeilen brauchen!

Tja, wenn´s da nicht das echte Leben wäre ...

Ich brauchte mal so´n Ding, um template member functions nachzubilden,
die ein Compiler nicht beherrschte, und das war immer noch besser, als
die Methode zigmal für unterschiedliche Parametertypen zu schreiben :-'
--
Wenn man möchte, daß etwas richtig gemacht wird, dann endet
es im allgemeinen damit, daß man es selber machen muß.

rj

Stefan Reuther

ungelesen,
25.01.2001, 08:58:4625.01.01
an
Hallo,

"Sebastian Moleski \(SurakWare\)" <smol...@surakware.com> wrote:
> "Stefan Reuther" <sr...@inf.tu-dresden.de>:
>> In leichter Variation verwende ich sowas gerade zur Implementation
>> von Closures. So richtig prall finde ich das zwar auch nicht,
>> aber IMHO besser, als denselben Code z.B. 6x hinzuschreiben.
>> Ich fand's zumindest praktisch, neulich einen Bug nur einmal
>> korrigieren zu müssen und nicht 6x.
>>
>> Wer eine bessere Möglichkeit kennt, immer her damit. Ich würde
>> ja etwas der Form `template<class A ...>' bevorzugen, aber das
>> geht leider nicht :-(

> Ich hab mal ein closure template geschrieben, das mit bis zu vier oder fünf
> Argumenten funktioniert und ohne Makros auskommt. Schreib mir, wenn Du es
> haben willst.

Bei mir ist das eine Hierarchie
Callee1<Ret, T>
+- Function1<Ret, T> (statische Funktion)
+- MemFun1<Ret, T> (dumb pointer)
+- SmartMemFun1<Ret, T> (smart pointer)

Callee2<Ret, T, U>
+- Function2<Ret, T, U>
+- MemFun2<Ret, T, U>
+- SmartMemFun2<Ret, T, U>

(für Callee0<Ret> .. Callee6<...>), plus der dazugehörigen Konstruktor-
funktion (z.B. `Function1<Ret, T> call(Ret (*func)(T))').

Das ist also 7x fast identischer Code, der IMHO nicht mit einem
weiteren Template erschlagbar ist. Wenn es z.B. nur um die
7 `MemFunX'-Klassen ginge, hätte ich auch auf das #define verzichtet.
Aber so sind das halt 28 Klassentemplates und 21 Funktionstemplates,
die ich mit einem #define (für je 4 Klassen+3 Funktionen) erschlage.


Stefan

Sebastian Moleski (SurakWare)

ungelesen,
25.01.2001, 12:14:4825.01.01
an
"Stefan Reuther" <sr...@inf.tu-dresden.de>:

> (für Callee0<Ret> .. Callee6<...>), plus der dazugehörigen Konstruktor-
> funktion (z.B. `Function1<Ret, T> call(Ret (*func)(T))').
Vielleicht verstehe ich etwas anderes unter closures als Du. Bei mir war ein
closure ein Zeiger auf eine Memberfunktionen und ein Zeiger auf ein
dazugehöriges Objekt.

sm

Stefan Reuther

ungelesen,
26.01.2001, 05:09:1126.01.01
an
Hallo,

"Sebastian Moleski \(SurakWare\)" <smol...@surakware.com> wrote:

> "Stefan Reuther" <sr...@inf.tu-dresden.de>:
>> (für Callee0<Ret> .. Callee6<...>), plus der dazugehörigen Konstruktor-
>> funktion (z.B. `Function1<Ret, T> call(Ret (*func)(T))').
> Vielleicht verstehe ich etwas anderes unter closures als Du. Bei mir war ein
> closure ein Zeiger auf eine Memberfunktionen und ein Zeiger auf ein
> dazugehöriges Objekt.

Yep. Allerdings kann man die "Zeiger" dumm oder smart ausführen,
und manchmal ist es gelegentlich nützlich, eine Funktion
ohne Objekt irgendwohin zu übergeben, wo sonst eine Closure
hinkommt. Das ist bei mir dann die abstrakte Klasse `Callee',
davon abgeleitet halt Implementationen für Closures und Funktions-
zeiger.


Stefan

Sebastian Moleski (SurakWare)

ungelesen,
26.01.2001, 10:49:4926.01.01
an
"Stefan Reuther" <sr...@inf.tu-dresden.de>:

> Hallo,
>
> "Sebastian Moleski \(SurakWare\)" <smol...@surakware.com> wrote:
> > "Stefan Reuther" <sr...@inf.tu-dresden.de>:
> >> (für Callee0<Ret> .. Callee6<...>), plus der dazugehörigen Konstruktor-
> >> funktion (z.B. `Function1<Ret, T> call(Ret (*func)(T))').
> > Vielleicht verstehe ich etwas anderes unter closures als Du. Bei mir war
ein
> > closure ein Zeiger auf eine Memberfunktionen und ein Zeiger auf ein
> > dazugehöriges Objekt.
>
> Yep. Allerdings kann man die "Zeiger" dumm oder smart ausführen,
> und manchmal ist es gelegentlich nützlich, eine Funktion
> ohne Objekt irgendwohin zu übergeben, wo sonst eine Closure
> hinkommt. Das ist bei mir dann die abstrakte Klasse `Callee',
> davon abgeleitet halt Implementationen für Closures und Funktions-
> zeiger.

Ich glaub ich versteh hier irgendwas nicht. Kannst Du vielleicht ein paar
Zeilen Beispielcode schreiben. Danke.

sm

Stefan Reuther

ungelesen,
29.01.2001, 09:22:2429.01.01
an
Hallo,

"Sebastian Moleski \(SurakWare\)" <smol...@surakware.com> wrote:
> "Stefan Reuther" <sr...@inf.tu-dresden.de>:

>> Yep. Allerdings kann man die "Zeiger" dumm oder smart ausführen,
>> und manchmal ist es gelegentlich nützlich, eine Funktion
>> ohne Objekt irgendwohin zu übergeben, wo sonst eine Closure
>> hinkommt. Das ist bei mir dann die abstrakte Klasse `Callee',
>> davon abgeleitet halt Implementationen für Closures und Funktions-
>> zeiger.

> Ich glaub ich versteh hier irgendwas nicht. Kannst Du vielleicht ein paar
> Zeilen Beispielcode schreiben. Danke.

Okay. Eine Signal-Slot-Implementation (I don't need no steenking `moc' ;-)
für einargumentige Signale, etwas vereinfacht. Die Idee dazu habe ich AFAIR
von Christopher Eltschka.

Ziel ist, daß ich irgendwo ein Signal rumliegen habe
Signal1<int> elementChanged;
und sich dort alle Objekte, die das Element betrachten, anmelden
können, z.B. als
elementChanged.add(this, &ThisClass::watcherMethod);
oder statische Funktionen
elementChanged.add(&staticFunction);
oder eben (falls wir smart pointer unterstützen würden)
elementChanged.add(smartptr, &PointeeClass::watcherMethod);
Für letzteres müßte eben noch eine Memberklasse `SmartPtrHandler'
und eine passende add-Methode eingebaut werden.

/*
* Signal1<T> = Signal, das einen Parameter vom Typ T
* nimmt. Also z.B. `Signal1<int> sig'. Als Signalhandler können
* dann Funktionen und Objektmethoden mit einem Argument vom
* Typ T angemeldet werden.
*/

template<class T>
class Signal1 {
/* Basisklasse "Signalhandler" */
struct Callee {
Callee* next;
virtual void raise(T arg) = 0;
};

/* Handler "Objektmethode" */
template<class A>
struct ObjHandler : public Callee {
A* obj;
void (A::*method)(T);
ObjHandler(A* aobj, void (A::*amethod)(T))
: obj(aobj), method(amethod) { }
void raise(T arg) { (obj->*method)(arg); }
};

/* Handler "statische Funktion" */
struct StaticHandler : public Callee {
void (*func)(T);
StaticHandler(void (*afunc)(T))
: func(afunc) { }
void raise(T arg) { func(arg); }
};
/* Liste aller Handler */
Callee* h;
public:
/* ctor/dtor */
Signal1() : h(0) { }

~Signal1() {
Callee* p;
while(h) {
p = h; h = h->next; delete p;
}
}

/*
* sig.add(main_form, &Tmain_form::method)
* -> wenn sig ausgelöst wird, rufe main_form->method(x)
* auf
*/
template<class A>
void add(A* obj, void (A::*method)(T)) {
Callee* h1 = new ObjHandler<A>(obj, method);
h1->next = h;
h = h1;
}

/*
* sig.add(funktion)
* -> funktion(x) wird aufgerufen
*/
void add(void (*func)(T)) {
Callee* h1 = new StaticHandler(func);
h1->next = h;
h = h1;
}

/*
* sig.raise(x)
* -> Signal auslösen, mit Parameter x
*/
void raise(T arg) {
Callee* q = h;
while(q.ptr()) {
q->raise(arg);
q = q->next;
}
}
};


Wenn du dieses Gerät nun auch für null- bis sechsstellige Funktionen
implementieren willst, greifst du halt entweder zu cut&paste,
oder zu einem Makro.


Stefan

Markus Schaaf

ungelesen,
29.01.2001, 10:20:5329.01.01
an
Stefan Reuther schrieb:

> Wenn du dieses Gerät nun auch für null- bis sechsstellige Funktionen
> implementieren willst, greifst du halt entweder zu cut&paste,
> oder zu einem Makro.

Wobei im Prinzip immer ein einzelnes Argument reicht, da
das beliebig komplexe Message-Objekte o.ä. sein können.
BTW: Ich würde soetwas einfach über virtuelle Funktionen
lösen, ohne Memberpointer - aber ich kenne Deine
Anforderungen nicht.

MfG

Stefan Reuther

ungelesen,
30.01.2001, 05:13:1630.01.01
an
Hallo,

Markus Schaaf <m.schaaf.e...@gmx.de> wrote:
> Stefan Reuther schrieb:

>> Wenn du dieses Gerät nun auch für null- bis sechsstellige Funktionen
>> implementieren willst, greifst du halt entweder zu cut&paste,
>> oder zu einem Makro.

> Wobei im Prinzip immer ein einzelnes Argument reicht, da
> das beliebig komplexe Message-Objekte o.ä. sein können.

Klar. Ich hab mir z.B. gerade genau für diesen Fall eine
Tupel-Klasse gebaut. Natürlich mit 5 Inkarnationen:
tuple2<A,B> bis tuple6<A,B,C,D,E,F>... Da ist der
Cut&Paste-Aufwand geringer ;)

> BTW: Ich würde soetwas einfach über virtuelle Funktionen
> lösen, ohne Memberpointer - aber ich kenne Deine
> Anforderungen nicht.

Virtuelle Funktionen haben den Nachteil, daß ich für jedes Signal
eine eigene Handlerklasse brauche, und jede behandelnde
Klasse davon ableiten muß. Du meinst ja sicher sowas:
class ItemChangedHandler {
public:
virtual void handle() = 0;
};
class MyObject : ItemChangedHandler, FileChangedHandler,
MouseChangedHandler {
// ...
};
Damit bekomme ich erstens Mehrfachvererbung ins Spiel (schlecht
für Smart Pointer), und verliere zweitens die Freiheit, abhängig
von Bedingungen verschiedene oder gar mehrere Funktionen pro
Objekt in die Handlerliste aufzunehmen. Außerdem will ich
Funktionen an Signale verfüttern können, die nie davon
geträumt haben ;-)

Warum gibt es eigentlich keine Closures in C++? Ist keiner
auf die Idee gekommen oder wurde der Vorschlag abgelehnt?
Der Borland-Compiler implementiert es ja immerhin...


Stefan

André Pönitz

ungelesen,
30.01.2001, 06:07:2430.01.01
an
Stefan Reuther <sr...@inf.tu-dresden.de> wrote:
> Warum gibt es eigentlich keine Closures in C++?

Gute Frage. Vermisse ich auch. Genaugenommen hast Du mit Funktionsobjekten
ja was in der Art, aber die Syntax bei komplexeren Funktionen ist krank...

> Ist keiner auf die Idee gekommen oder wurde der Vorschlag abgelehnt?

Schau Dir mal http://lambda.cs.utu.fi an. Ist schnucklig.

Andre'

PS:

> Der Borland-Compiler implementiert es ja immerhin...

Wie? (Mail reicht, falls das OT wird)
--
André Pönitz ........................................ poe...@htwm.de

0 neue Nachrichten