Hallo,
ich möchte eine Funktion erstellen, die einen Zeiger auf eine Funktion
mit gleicher Signatur wie die Funktion selbst zurückgibt. Also so, dass
man die Funktion mittels
f(bla)(blub)(foo)...
beliebig oft direkt nacheinander aufrufen kann. Ist das in C(++) möglich
und wenn ja, wie hat der Funktionskopf auszusehen?
- jgdo -
Klaus Wachtler schrieb:> Von wegen parse error ... :-)
Der parse error war schlichtweg in meinem Kopf: ich habe einfach nicht
verstanden, was er wollte und wozu das Ganze gut ist. Letzteres weiß ich
immer noch nicht.
Sein Problem ist in C in der Tat nicht trivial bzw. vielleicht gar nicht
lösbar, weil man den Typ "Zeiger auf eine Funktion..." in derselben
Typdefinition noch nicht als Rückgabe der Funktion verwenden kann.
Wie will man dann eine Funktion definieren, die einen Zeiger auf sich
selbst liefert? So eine leere forward-Deklaration wie bei structs gibt
es für Funktionen ja nicht.
Danke für die Antworten Leute.
@Karl Heinz Buchegger
Das ist eine Möglichkeit, aber ich wollte die Casts eben vermeiden.
Schade dass es direkt nicht geht.
@Klaus Wachtler
Ist eine Klasse und keine Funktion.
@alle
mir gings eher um das Prinzip, eine echte Anwendung dafür habe ich
nicht. Ich habe nur eine Funktion, die mehrmals nacheinander mit
verschiedenen Parametern aufgerufen wird und ich wollte mal einfach
etwas Tipparbeit sparen ;)
int res;
void *Func(int p1) {
res += p1;
return &Func;
}
int main(void) {
res = 0;
int (*p)(int) = Func(5);
(*p)(10);
printf("res=%d", res);
}
Also irgendwie krieg ich das Func(x)(y) nicht hin. Weiß jemand anderes
weiter?
Kan asta schrieb:> int res;>> void *Func(int p1) {> res += p1;> return &Func;> }
Du hast die Problemstellung noch nicht verstanden
> Also irgendwie krieg ich das Func(x)(y) nicht hin. Weiß jemand anderes> weiter?
Sieh dir den FAQ Link von weiter oben an. Da sind 2 Lösungsmöglichkeiten
gegeben. Beide nicht besonders schön.
Das Problem, wie schon weiter oben vermerkt, besteht darin, dass es
sowas wie eine 'Forward-Deklaration' für Funktionspointer nicht gibt.
Die würde man aber brauchen, damit man einen Funktionspointer machen
kann, auf eine Funktion die genau diesen Funktionspointer-Typ liefert.
Hm, was spricht dagegen die Parameter in ein Array zu packen und über
dieses zu Iterieren? Ob es nun besser ist, das Array als ganzes an die
Funktion zu übergeben oder jeden Parameter einzeln ist dann wieder ein
anderes Thema. (ersteres ist besser lesbar und sollte auch in
schnellerem Code resultieren, letzteres ist universeller)
max schrieb:> Hm, was spricht dagegen die Parameter in ein Array zu packen und über> dieses zu Iterieren?
Na, ja. Das ganze war ja bis jetzt nur eine Spielerei :-)
so richtig geil wird das ganze dann, wenn eine Funktion (abhängig vom
Parameter) nicht sich selbst zurückgibt, sondern einen Pointer auf eine
ganz andere Funktion. Man kann da dann ein ganzes Netzwerk von
Funktionsaufrufen hinter der harmlos anmutenden Syntax
foo(4)(5)(6)(8);
(oder auch
do {
f = f(Werte[i++]);
} while( f );
)
aufbauen, das kein Mensch mehr ohne 5 Liter Kaffee und eine Großpackung
Baldrian durchschaut :-) Sowas nennt man dann "aktive
Arbeitsplatzsicherung".
Karl Heinz Buchegger schrieb:> aufbauen, das kein Mensch mehr ohne 5 Liter Kaffee und eine Großpackung> Baldrian durchschaut :-) Sowas nennt man dann "aktive> Arbeitsplatzsicherung".
und der Sieg beim IOCCC sicher ist :)
Karl Heinz Buchegger schrieb:> aufbauen, das kein Mensch mehr ohne 5 Liter Kaffee und eine Großpackung> Baldrian durchschaut :-) Sowas nennt man dann "aktive> Arbeitsplatzsicherung".
You made my day :D
kann man nicht einfach mit einem Makro einen Zeiger auf ein Array von
Parametern übergeben und dann die Funktion einfach mehrmals aufrufen?
sowas wie
1
#define foo(var) foo_fctn({ (var) })
2
3
//oder falls das nicht geht:
4
5
#define foo(var) \
6
int array[]={ (var) , 0x7FFF }; \
7
foo_fctn(array);
8
9
intfoo_fctn(int*array)
10
{
11
inti=0;
12
while(array[i]!=0x7FFF)
13
{
14
res+=foo_nocheine(array[i]);
15
i++;
16
}
17
returnres;
18
}
19
20
var=foo(1);
21
var=foo(1,2);
22
var=foo(1,2,3);
23
var=foo(1,2,3,4);
(alles nicht getesten, hab auf meinem Laptop keine IDE ^^)
EDIT: nagut, das array wird bei mehrfacher Verwendung des Makros im
selben Gültigkeitsbereich Probleme machen aber das Prinzip sollte ja
ersichtlich sein oder?
EDIT2: werden die Kommas Probleme machen? vielleicht Klammern
"Übergeben" und temporär Klammern als Komma definieren? xD (falls die
erste Variante nicht funktioniert)
Karl Heinz Buchegger schrieb:> Sowas nennt man dann "aktive Arbeitsplatzsicherung".
In richtig guten Firmen kriegen die Leute eine Abmahnung, die solchen
Code verfassen. ;-)
Karl Heinz Buchegger schrieb:> Sowas nennt man dann "aktive> Arbeitsplatzsicherung".
Nope, das nennt man Funktionale Programmierung und ist absolut
faszinierend, wenn man sich für theoretische Informatik interessiert.
Dani Zwirner schrieb:> So gehts:> [...]> aber leider nur mit zweifachem Aufruf. Beim dreifachen Aufruf>
1
>f(1)(2)(3);
2
>
> meint der gcc error: called object ‘f(1)(2)’ is not a function
((fp) (f(1)(2)))(3);
bzw.
((fp) ((fp) (f(1)(2)))(3))(4);
usw.
funktionieren. Das sieht aber nicht mehr so schön aus ;-)
Karl Heinz Buchegger schrieb:> so richtig geil wird das ganze dann, wenn eine Funktion (abhängig vom> Parameter) nicht sich selbst zurückgibt, sondern einen Pointer auf eine> ganz andere Funktion [..] das kein Mensch mehr ohne 5 Liter Kaffee und> eine Großpackung Baldrian durchschaut :-)> Sowas nennt man dann "aktive Arbeitsplatzsicherung"
Oder Method Chaining/Fluent Interface:
http://en.wikipedia.org/wiki/Method_chaininghttp://en.wikipedia.org/wiki/Fluent_interface
Ich nutze das ab und an mal konnte mich aber bisher noch nicht im großen
Stil dafür erwärmen...
Wird zwar immer im Zusammenhang mit OO genannt, aber wieso sollte man
das nicht auch mal in C umsetzen? Der arme Compiler...
Klaus Wachtler schrieb:> Wieso?> Das ist nur eine andere Form eines Zustandsautomats - für den wird man> auch nicht automatisch abgemahnt.
Normalerweise sollte es in einer Firma Richtlinien für die Codierung
geben. Wenn die Firma Wert auf Qualität legt (das tut freilich nicht
jede), dann sorgt sie auch dafür, dass diese Richtlinien eingehalten
werden. Solche Tools wie z.B. MISRA C++ Code Checker mögen in der Regel
"arbeitsplatzsichernden Code" nicht besonders :-)
jgdo schrieb:> ich möchte eine Funktion erstellen, die einen Zeiger auf eine Funktion> mit gleicher Signatur wie die Funktion selbst zurückgibt.
In Sprachen mit dynamischer Typisierung (z.B. Python) ist das kein
Problem:
1
def f(x):
2
print('f called with', x)
3
return f
4
5
f(1)(2)(3)(4)
liefert
1
f called with 1
2
f called with 2
3
f called with 3
4
f called with 4
Viele Sprachen mit statischer Typisierung scheinen aber Probleme zu
haben, den Typ dieser Funktion compiler-intern darzustellen. Auch in
Haskell, wo man das Ausdenken der Funktionssignaturen i.Allg. dem
Compiler überlassen und ganz lapidar
Das ist dort aber kein großes Problem, da dieses Konstrukt sowieso nur
für seiteneffektbehaftete Funktionen von Nutzen ist, die es in Haskell
gar nicht gibt.
Läubi .. schrieb:> Oder Method Chaining/Fluent Interface:
Auch ganz interessant in diesem Zusammenhang:
http://en.wikipedia.org/wiki/Continuation-passing_style