Forum: Mikrocontroller und Digitale Elektronik Funktion, welches je nach Datentype der Eingangsvariablen anders reagiert - geht sowas ?


von Tom (Gast)


Lesenswert?

Guten Abend,

sehr vereinfacht gesagt habe ich eine Funktion welches aus einer Zahl 
einen String macht.

Aktuell habe ich dafür vier Funktionen:

void funct1( uint8_t z, char* Buffer)
void funct2( uint16_t z, char* Buffer)
void funct3( int8_t z, char* Buffer)
void funct4( int16_t z, char* Buffer)

Eigentlich machen die Funktionen fast alle das Gleiche  - daher habe ich 
gedacht, dass es doch eine Möglichkeit geben müsste, den Typ einer 
Variablen zu "testen" und der Funktion einen "undefinierten 
Variablentyp" zu übergeben.


Geht sowas ?

void funct1( undefined z, char* Buffer)

Wenn ja - wie genau?


Danke!

von Klimatester (Gast)


Lesenswert?

https://en.wikipedia.org/wiki/Function_overloading
https://en.wikipedia.org/wiki/Variant_type

Tom schrieb:
> Wenn ja - wie genau?

Kommt drauf an welche Sprache und Compiler.

von Einer K. (Gast)


Lesenswert?

z.B. C++ verwenden

Damit möglich:
-Funktionen überladen
-Template Funktionen

von Tom (Gast)


Lesenswert?

Sorry:

Sprache C,
Compiler GCC (AVR Studio)
Ziel: Möglichst sparsam mit Ressourcen

von Einer K. (Gast)


Lesenswert?

Tom schrieb:
> Sprache C,
Dann nein.

Tom schrieb:
> Compiler GCC (AVR Studio)
C++ möglich

Tom schrieb:
> Ziel: Möglichst sparsam mit Ressourcen
Da tun sich C und C++ nichts.

von A. S. (Gast)


Lesenswert?

_Generic

von zitter_ned_aso (Gast)


Lesenswert?

1
#include <stdio.h>
2
#include <stdint.h>
3
4
void funct1( uint8_t z, char* Buffer){
5
    puts("fkt1");
6
}
7
void funct2( uint16_t z, char* Buffer){
8
    puts("fkt2");
9
}
10
11
void funct3( int8_t z, char* Buffer){
12
    puts("fkt3");
13
}
14
15
void funct4( int16_t z, char* Buffer){
16
    puts("fkt4");
17
}
18
19
20
21
#define my_function(x, y) _Generic((x),\
22
        uint8_t: funct1,\
23
        uint16_t: funct2,\
24
        int8_t: funct3,\
25
        int16_t: funct4\
26
    )(x, y) 
27
28
29
30
int main(void){
31
32
    uint8_t x1=1;
33
    my_function(x1, "bufer1");
34
35
    uint16_t x2=2;
36
    my_function(x2, "bufer2");
37
    
38
    int8_t x3=3;
39
    my_function(x3, "bufer3");
40
    
41
    int16_t x4=4;
42
    my_function(x4, "bufer4");
43
44
    return 0;
45
}

Ich hoffe es ist richtig.  Bei zwei Parametern ist es kompliziert (aber 
hier bleibt ja der zweite Parameter gleich == spielt keie Rolle)

von gaudiamus (Gast)


Lesenswert?

Wie wärs wenn du eine Funktion baust die alle Fälle abdeckt wobei 
zusätzlich der Typ mit den Parametern übergeben wird und dann die 4 
Funktionen diese allgemeine Funktion aufrufen lässt? Je nach Parameter 
wird dann eben mit 00 aufgefüllt bzw. das Vorzeichen ausgewertet

von nfet (Gast)


Lesenswert?

void func(void* zahl, int typ, char* buffer)

von gaudiamus (Gast)


Lesenswert?

Vielleicht lässt sich auch was mit präprozessor-Makros machen und 
tricksen mit sizeof() oder so ;)

von Axel S. (a-za-z0-9)


Lesenswert?

zitter_ned_aso schrieb:

[Generics]

gaudiamus schrieb:
> Wie wärs wenn du eine Funktion baust die alle Fälle abdeckt wobei
> zusätzlich der Typ mit den Parametern übergeben wird
...

Unübersichtlich. Im zweiten Fall auch unsinnig (wenn er bei jedem 
Funktionsaufruf im Code selber auf den Typ des Parameters schauen muß, 
kann er auch gleich jeweils die richtige Funktion wählen).

Genau dafür hat C++ die Funktionsüberladung bekommen. Einfach alle 4 
Funktionen gleich nennen und dann sucht sich der Compiler bei jedem 
Aufruf jeweils die raus, die zu den verwendeten Argumenten paßt. Wenn er 
den AVR-GCC benutzt, dann hat er C++ zur Hand. Am Ende ist das auch 
nichts anderes als die Lösung mit Generics. Wahrscheinlich sieht sogar 
der Objectcode jeweils gleich aus. Nur die Symbole für die 
Funktions-Einsprünge werden mit C++ anders aussehen 
(https://en.wikipedia.org/wiki/Name_mangling)

Und wenn der TE das wegen einer C++ Phobie nicht mag, dann soll er es 
halt lassen. keine Arme, keine Kekse!

von zitter_ned_aso (Gast)


Lesenswert?

eigentlich passen ja int8_t / uint8_t-Werte in eine int16_t-Variable.

vielleicht ein paar Fuktionen streichen.

von gaudiamus (Gast)


Lesenswert?

Wie wär's wenn Du einfach alles nach int 32 castestest?(Das ist der 
Konjunktiv;)

von Peter D. (peda)


Lesenswert?

Tom schrieb:
> Ziel: Möglichst sparsam mit Ressourcen

Ziel verfehlt.
Das Überladen mit C++ erzeugt trotzdem alle 4 verschiedenen Funktionen, 
es wird nur automatisch die richtige aufgerufen.

Will man optimieren, dann zeig mal, was konkret die verschieden machen 
sollen.
Ein Ansatz wurde ja hier genannt:
Beitrag "Re: Funktion, welches je nach Datentype der Eingangsvariablen anders reagiert - geht sowas ?"

von Axel S. (a-za-z0-9)


Lesenswert?

Peter D. schrieb:
> Tom schrieb:
>> Ziel: Möglichst sparsam mit Ressourcen
>
> Ziel verfehlt.
> Das Überladen mit C++ erzeugt trotzdem alle 4 verschiedenen Funktionen

Ja. Genauso wie die C-Variante mit 4 Einzelfunktionen. Unabhängig davon, 
ob man noch Generics drüberstülpt oder nicht.

> Will man optimieren

Der Ruf nach Optimierung erscheint mir hier fehl am Platze. Was will man 
denn da optimieren? Entweder eine dieser Funktionen wird gebraucht 
(vulgo: aufgerufen), dann muß sie der Compiler auch generieren. Oder sie 
wird nicht gebraucht, dann kann er sie weglassen. Und mit den richtigen 
Optionen für Compiler und Linker machen gcc und GNU ld das auch.

Wenn es darum geht, möglichst kompakten Binärcode zu erzeugen, dann 
würde man damit anfangen, gar nicht erst zig Funktionen zu schreiben, 
die am Ende alle nur das gleiche machen.

Andererseits ist das vermutlich auch wieder ein Fall von verfrühter 
Optimierung. Der TE zeigt zwar keine Implementierung, aber es soll ja 
wohl eine Art sprintf() werden. Da machen seine "Funktionen" 
wahrscheinlich kaum mehr, als itoa() und utoa() aufzurufen. Der 
eigentliche Funktionsrumpf dürfte minimal sein, was diese Funktionen zu 
idealen Kandidaten für inlining macht.

von A. B. (Gast)


Lesenswert?

Warum das Rad neu erfinden? "sprintf" tut's doch. Und wenn's um eine 
"Minimalversion" geht, schreibt man sich halt eine abgespeckte Version, 
aber weiterhin mit varargs wie beschrieben:

https://en.wikipedia.org/wiki/Variadic_function#In_C

Nachteil ist, dass man die Information, um welchen Datentyp es geht,
explizit der Funktion mitgeben muss. Und der Compiler prüft halt nicht,
ob der Datentyp stimmt, ggf. gibt's also Chaos ...

von Einer K. (Gast)


Lesenswert?

A. B. schrieb:
> "sprintf"
Ist ungefähr das Gegenteil von optimieren.

von Alex D. (daum)


Lesenswert?

A. B. schrieb:
> Nachteil ist, dass man die Information, um welchen Datentyp es geht,
> explizit der Funktion mitgeben muss. Und der Compiler prüft halt nicht,
> ob der Datentyp stimmt, ggf. gibt's also Chaos ...

Es gibt beim gcc das attribute __attribute__((format(printf,1,2))). 
Wobei hier 1 der Index des String Formates ist (Index beginnt bei 1) und 
2 der Index des ersten Arguments, das überprüft werden soll.
https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html

von Zeno (Gast)


Lesenswert?

Klimatester schrieb:
> Kommt drauf an welche Sprache und Compiler.

Da hat Klimatester recht.

Mit Objectpascal (Delphi) ginge so etwas. Objectpascal kennt den Typ 
Variant, der alle Datentypen abbilden kann. Dort gibt es auch Funktionen 
mit denen man ermitteln kann von welchem Typ die Daten sind.
Wo Licht ist ist natürlich auch Schatten:
 -variante Typen brauchen mehr Speicher
 -die Verarbeitung variander Typen ist langsamer
Ich habe Varianten für den umgekehrten Weg eingesetzt um aus beliebigen 
numerischen Strings Zahlen zu machen. Die Funktion liefert ein Ergebnis 
vom Typ Variant, das man allen Zahlentypen in Delphi zu weisen kann.

In C scheint das nicht so einfach zu sein. Das was hie an Code gezeigt 
wurde erzeugt letztendlich auch 4 Funktionen.

Arduino Fanboy D. schrieb:
> Damit möglich:
> -Funktionen überladen
Auch das Überladen sind am Ende mehrere Funktionen, allerdings mit dem 
Vorteil das alle Funktionen den gleichen Namen besitzen und an Hand des 
Datentyps entschieden wird welche Funktion letztendlich aufgerufen wird.

nfet schrieb:
> void func(void* zahl, int typ, char* buffer)
Einzige Möglichkeit in C scheint zu sein, indem ich der Funktion 
mitteile welchen Datentyp ich übergebe.

von Programmierer (Gast)


Lesenswert?

Zeno schrieb:
> Mit Objectpascal (Delphi) ginge so etwas. Objectpascal kennt den Typ
> Variant, der alle Datentypen abbilden kann. Dort gibt es auch Funktionen
> mit denen man ermitteln kann von welchem Typ die Daten sind.

Genau das geht in C++ auch, C++ hat ebenfalls einen Typ variant.

Zeno schrieb:
> Einzige Möglichkeit in C scheint zu sein, indem ich der Funktion
> mitteile welchen Datentyp ich übergebe.

Das ist aber sogar weniger effizient als Überladungen in C++, weil 
dadurch zusätzlich die Laufzeit-Unterscheidung hinzu kommt.

Axel S. schrieb:
> Am Ende ist das auch
> nichts anderes als die Lösung mit Generics. Wahrscheinlich sieht sogar
> der Objectcode jeweils gleich aus.

Genau so ist es. Nur dass Funktionsüberladungen in C++ doch deutlich 
einfacher & übersichtlicher sind.

von A. B. (Gast)


Lesenswert?

Alex D. schrieb:

> Es gibt beim gcc das attribute __attribute__((format(printf,1,2))).
> Wobei hier 1 der Index des String Formates ist (Index beginnt bei 1) und
> 2 der Index des ersten Arguments, das überprüft werden soll.
> https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html

Jaaaa, aber nur wenn man sich an die "printf"-Konventionen für den 
Format-String hält. Dann ist man aber schon fast wieder beim normalen 
"sprintf". Wenn man nur eine abgespeckte Version oder gänzlich andere 
implementiert, hilft das wenig.
Man kann freilich den gcc auch eine selbstgestrickte Konvention 
beibringen ...

von Rolf M. (rmagnus)


Lesenswert?

Ich würde zu C++ mit templates raten. Was die Codegröße betrifft, macht 
das zwar keinen Unterschied zu überladenen Funktionen - es werden immer 
noch Funktionen für alle Typen generiert, die man nutzt, aber man muss 
wenigstens nicht n separate Implementationen der selben Funktion 
schreiben, die sich nur im übergebenen Typ und der Anzahl der 
auszuwertenden Bits unterscheiden.

A. B. schrieb:
> Jaaaa, aber nur wenn man sich an die "printf"-Konventionen für den
> Format-String hält. Dann ist man aber schon fast wieder beim normalen
> "sprintf". Wenn man nur eine abgespeckte Version oder gänzlich andere
> implementiert, hilft das wenig.

Wenn man den Format-String komplett anders aufbaut, magst du recht 
haben.
Aber solange man ein Subset mit gleicher Syntax wie bei printf 
verwendet, klappt das natürlich schon. Wenn der übergebene Typ nicht zum 
Format-Specifier passt, gibt es immer noch eine Warnung.

: Bearbeitet durch User
von Programmierer (Gast)


Lesenswert?

Rolf M. schrieb:
> aber man muss
> wenigstens nicht n separate Implementationen der selben Funktion
> schreiben, die sich nur im übergebenen Typ und der Anzahl der
> auszuwertenden Bits unterscheiden.

Wenn das denn so ist. Wenn die Funktionen sonst komplett unterschiedlich 
sind, bringen templates hier gar nichts. Wenn die Funktionen sich derart 
ähnlich sind, sind templates sinnvoll, und produzieren auch nicht mehr 
Code als einzeln manuell implementierte Funktionen.

von Rolf M. (rmagnus)


Lesenswert?

Programmierer schrieb:
> Rolf M. schrieb:
>> aber man muss wenigstens nicht n separate Implementationen der selben
>> Funktion schreiben, die sich nur im übergebenen Typ und der Anzahl der
>> auszuwertenden Bits unterscheiden.
>
> Wenn das denn so ist. Wenn die Funktionen sonst komplett unterschiedlich
> sind, bringen templates hier gar nichts.

Nun, das Ursprungsposting klang für mich nicht danach, dass diese 
Funktionen alle vollkommen unterschiedlich implementiert sind bzw. sein 
müssten.

von A. S. (Gast)


Lesenswert?

Zeno schrieb:
> Einzige Möglichkeit in C scheint zu sein, indem ich der Funktion
> mitteile welchen Datentyp ich übergebe.

Hast Du _Generics oben gelesen und verstanden? Das ist im Endeffekt 
genauso wie eine überladene Funktion in C++.

von Stefan F. (Gast)


Lesenswert?

Das geht deswegen nicht in C/C++ weil ein Zeiger auf unbekannte Daten 
nichts anderes ist, als die Adresse eines Speicherbereiches im RAM. 
Weder der Zeiger noch die Daten enthalten irgendwelche Informationen 
über die Art und Größe der Daten - es sei denn, du legst diese 
Informationen mit in den Daten ab. Dann machst du im Grunde genommen das 
zu Fuß, was C++ mit std::variant macht.

Wenn du aber std::variant bzw. deine selbst gebastelte Datenstruktur mit 
Typ-Informationen verwendest, dann bist du auch dazu gezwungen. Die 
Funktion lässt sich dann nicht mit andere Datenstrukturen verwenden. Sie 
zwingt dich dazu, alles in einen variant zu verpacken.

von Programmierer (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Weder der Zeiger noch die Daten enthalten irgendwelche Informationen
> über die Art und Größe der Daten

Der Typ der Variablen, welcher dem Compiler bekannt ist enthält diese 
Information. Daher kann der Compiler den Aufruf an den richtigen 
Overload oder die richtige Generic-Function erzeugen. Diese Auflösung 
geschieht aber während des Kompilierens, und zur Laufzeit ist diese 
Information nicht verfügbar ("Type Erasure"). C und C++ besonders sind 
stark typisierte Sprachen, d.h. der Compiler hat diese Information eben 
doch.

von Axel S. (a-za-z0-9)


Lesenswert?

Rolf M. schrieb:
> Ich würde zu C++ mit templates raten.

Ich nicht. ich sehe nämlich bei dieser Anwendung gar keinen Vorteil von 
Templates.

> Was die Codegröße betrifft, macht
> das zwar keinen Unterschied zu überladenen Funktionen - es werden immer
> noch Funktionen für alle Typen generiert, die man nutzt, aber man muss
> wenigstens nicht n separate Implementationen der selben Funktion
> schreiben

Jein. Man kann mit Templates natürlich eine generische Implementierung 
schreiben. Aber nur dann, wenn es eine solche generische Implementierung 
auch gibt. Wie sollte die denn aber aussehen? Das ist ja gerade der 
Witz, daß man für verschieden lange Integer beiderlei signedness auch 
jeweils verschiedene _X_toa Funktionen aus der stdlib aufrufen muß. Mit 
anderen Worten: man muß separate Implementierungen für diese Typen 
explizit hinschreiben.

Schon schwindet jeglicher Vorteil gegenüber normaler 
Funktionsüberladung. Aber man hat den syntaktischen Overhead von 
Templates.

Wenn man eine C++ Lösung haben will, würde man eher das Streams 
Interface benutzen. Und ganz besonders würde man nicht mit char* Buffern 
herumhantieren. C-Strings und nackte Pointer haben in einem C++ Programm 
nichts zu suchen. Außer vielleicht da, wo man mit legacy C-Code 
interoperieren muß.

von Stefan F. (Gast)


Lesenswert?

Programmierer schrieb:
> Der Typ der Variablen, welcher dem Compiler bekannt ist enthält diese
> Information. Daher kann der Compiler den Aufruf an den richtigen
> Overload oder die richtige Generic-Function erzeugen

Ja schon, aber nur bei C++.

Der TO wollte aber nicht viele Varianten der Funktion, zwischen denen 
der Compiler wählt, sondern eine Funktion die sich selbst darum kümmert 
- zur Laufzeit.

von Programmierer (Gast)


Lesenswert?

Axel S. schrieb:
> Das ist ja gerade der
> Witz, daß man für verschieden lange Integer beiderlei signedness auch
> jeweils verschiedene _X_toa Funktionen aus der stdlib aufrufen muß.

Es sei denn, man schreibt eine generische X_toa-Funktion welche das 
automatisch für alle Breiten korrekt macht. Das ist recht einfach.

Axel S. schrieb:
> Wenn man eine C++ Lösung haben will, würde man eher das Streams
> Interface benutzen.

Die sind leider nicht sehr Mikrocontroller-Geeignet. Selbst Arduino 
nutzt Overloads: 
https://www.arduino.cc/reference/de/language/functions/communication/serial/print/

Stefan ⛄ F. schrieb:
> Ja schon, aber nur bei C++.

Nein, auch bei C. Sonst könnte der Compiler keine Fehlermeldung ausgeben 
bei Dingen wie "puts(42);", wenn er nicht wüsste, dass "42" vom Typ 
"int" ist, aber "puts" ein "const char*" Argument braucht. Außerdem 
braucht er das für _Generic.

Stefan ⛄ F. schrieb:
> Der TO wollte aber nicht viele Varianten der Funktion, zwischen denen
> der Compiler wählt, sondern eine Funktion die sich selbst darum kümmert
> - zur Laufzeit.

Ganz sicher?

von Rolf M. (rmagnus)


Lesenswert?

Axel S. schrieb:
> Wenn man eine C++ Lösung haben will, würde man eher das Streams
> Interface benutzen. Und ganz besonders würde man nicht mit char* Buffern
> herumhantieren. C-Strings und nackte Pointer haben in einem C++ Programm
> nichts zu suchen. Außer vielleicht da, wo man mit legacy C-Code
> interoperieren muß.

Wir sprechen hier von einer ressourcensparenden Implementation auf 
AVR-µCs.

Stefan ⛄ F. schrieb:
> Der TO wollte aber nicht viele Varianten der Funktion, zwischen denen
> der Compiler wählt, sondern eine Funktion die sich selbst darum kümmert
> - zur Laufzeit.

Ich hab das nicht so verstanden, dass er das unbedingt zur Laufzeit tun 
will, sondern eben, dass er sich das Schreiben von mehreren fast genau 
gleichen Funktionen ersparen möchte.

von Stefan F. (Gast)


Lesenswert?

Programmierer schrieb:
>> Der TO wollte aber nicht viele Varianten der Funktion, zwischen denen
>> der Compiler wählt, sondern eine Funktion die sich selbst darum kümmert
>> - zur Laufzeit.

> Ganz sicher?

So habe ich ihn jedenfalls verstanden. Warum auch immer, besonders 
Sinnvoll kommt es mir nicht vor.

von Einer K. (Gast)


Lesenswert?

Rolf M. schrieb:
> Ich hab das nicht so verstanden, dass er das unbedingt zur Laufzeit tun
> will, sondern eben, dass er sich das Schreiben von mehreren fast genau
> gleichen Funktionen ersparen möchte.

Das können einem _Generic und auch C++ Überladungen nicht ersparen.
Macht die Sache nur einfacher, für den Nutzer.

Per Template Funktion, bekommt man das alles in einen Funktionsrumpf 
gestopft. Wird hässlich.
Aber am Ende des Tages werden die spezialisierten Funktionen dann doch 
vom Compiler automatisch generiert.

Nix mit Speichereinsparung.
Denn es muss getan werden, was getan werden muss.

von Axel S. (a-za-z0-9)


Lesenswert?

Stefan ⛄ F. schrieb:
> besonders Sinnvoll kommt es mir nicht vor.

+1

von A. S. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Der TO wollte aber nicht viele Varianten der Funktion, zwischen denen
> der Compiler wählt, sondern eine Funktion die sich selbst darum kümmert
> - zur Laufzeit.

Zur Laufzeit macht wenig Sinn. Weshalb sollte das der TO gemeint haben.

Eine typische Anwendung ist eine Diagnose-Funktionalität. Ich möchte 
Variablen listen, über die ein Code automatisch traversiert. Und je nach 
Typ soll der Compiler deren Wert sinnvoll darstellen, ohne dass ich das 
angeben muss (oder überhaupt schon weiß, vielleicht ändert es sich ja)

Für die Größe reicht sizeof, geschenkt.

aber ob ich -1 oder 255 anzeigen soll, ist schon wichtiger. Wenn ich die 
Variablen MyIndex, MyCount und MyWhatever habe, möchte ich vielleicht 
einfach
 Add(MyCount), Add(MyIndex), Add(MyWhatever) hinschreiben.

Ein paralleles Pflegen des Types (wie z.B. bei printf) ist eine üble 
Sache. (wobei printf und Co ja noch übler werden, wenn int mal 2 und mal 
4 Byte groß sein kann. Ja, geht, herhackt die Strings aber noch weiter)

von c-hater (Gast)


Lesenswert?

Programmierer schrieb:

> Wenn die Funktionen sonst komplett unterschiedlich
> sind, bringen templates hier gar nichts. Wenn die Funktionen sich derart
> ähnlich sind, sind templates sinnvoll, und produzieren auch nicht mehr
> Code als einzeln manuell implementierte Funktionen.

Unsinn.

Jede Verwendung für eine beliebige Kombination konkreter Typen erzeugt 
natürlich zwangsweise Code für eben diese Typkombination. D.h.: dieser 
abstrakte Quatsch ist nur dann ohne Impact auf die Codegröße, solange er 
nicht tatsächlich konkret benutzt wird.

Sprich: dein Code auf Quelltextebene wird durch Sachen wie Templates und 
überladene Funktionen übersichtlicher, weil kürzer. Das ist schon alles, 
was diese Syntax-Gimmicks bringen...

Da, wo tatsächlich geackert wird, auf der Ebene der Hardware, bringt das 
garnix. Es ist eher so, dass durch diese beschwingte Leichtigkeit auf 
der abgehobenen Ebene des Hochsprachencodes die Tendenz steigt, Code, 
den man tatsächlich vereinheitlichen könnte, nicht wirklich zu 
vereinheitlichen, sondern immer und immer wieder zu PHYSISCH zu 
manifestieren. Das schadet der Performance direkt immerhin so gut wie 
garnicht, ist aber bezüglich der Codegröße und damit bei vielen 
Architekturen indirekt (durch die begrenzte Größe von Caches) doch auch 
wieder bezüglich der Performance ziemlich teuer.

Die Auswirkungen dieser krassen Fehlentwicklung kann man sich an 
praktisch jeder üblichen PC-Anwendung ansehen, wenn man sie über die 
Jahre mit konstanter Hardwarepower beobachtet...

von Programmierer (Gast)


Lesenswert?

c-hater schrieb:
> Jede Verwendung für eine beliebige Kombination konkreter Typen erzeugt
> natürlich zwangsweise Code für eben diese Typkombination.

Genau den Code, den man bei manueller Implementation auch erzeugt hätte. 
Nullsummenspiel.

c-hater schrieb:
> Das ist schon alles, was diese Syntax-Gimmicks bringen...

Das ist aber eine Menge. Vermeidung von Wiederholung hilft gegen Fehler 
und unwartbaren Code.

c-hater schrieb:
> Da, wo tatsächlich geackert wird, auf der Ebene der Hardware, bringt das
> garnix.

Das ist nicht die einzige Ebene, die zählt. Git bringt auf der Hardware 
Ebene auch nix. Verwenden sollte man es trotzdem.

c-hater schrieb:
> Es ist eher so, dass durch diese beschwingte Leichtigkeit auf der
> abgehobenen Ebene des Hochsprachencodes die Tendenz steigt, Code, den
> man tatsächlich vereinheitlichen könnte, nicht wirklich zu
> vereinheitlichen, sondern immer und immer wieder zu PHYSISCH zu
> manifestieren.

Hast du dafür auch nur den Hauch eines Beweises? Diese Argumentation ist 
so wie zu sagen "wenn der Handwerker eine Bohrmaschine zur Verfügung 
hat, tendiert er dazu diese für alles zu benutzen. Daher sollte man 
Bohrmaschine gar nicht verwenden."
Außerdem werden duplizierte templates sowieso wegoptimiert.

c-hater schrieb:
> Die Auswirkungen dieser krassen Fehlentwicklung kann man sich an
> praktisch jeder üblichen PC-Anwendung ansehen, wenn man sie über die
> Jahre mit konstanter Hardwarepower beobachtet...

Die sind sowieso kaum noch in C++ geschrieben, und wenn dann sind 
templates nicht an Performance Problemen schuld. Die Haupt Bremse in den 
meisten Fällen sind schlecht konstruierte Datenstrukturen und 
Algorithmen. Die Sprache ist da eher drittrangig.

von Rolf M. (rmagnus)


Lesenswert?

Arduino Fanboy D. schrieb:
> Rolf M. schrieb:
>> Ich hab das nicht so verstanden, dass er das unbedingt zur Laufzeit tun
>> will, sondern eben, dass er sich das Schreiben von mehreren fast genau
>> gleichen Funktionen ersparen möchte.
>
> Das können einem _Generic und auch C++ Überladungen nicht ersparen.

Deshalb habe ich ja auch nicht die, sondern Templates empfohlen.

> Per Template Funktion, bekommt man das alles in einen Funktionsrumpf
> gestopft. Wird hässlich.

Glaube ich nicht.

> Aber am Ende des Tages werden die spezialisierten Funktionen dann doch
> vom Compiler automatisch generiert.

Das habe ich auch schon geschrieben.

c-hater schrieb:
> Jede Verwendung für eine beliebige Kombination konkreter Typen erzeugt
> natürlich zwangsweise Code für eben diese Typkombination.

Soweit waren wir schon.

> Sprich: dein Code auf Quelltextebene wird durch Sachen wie Templates und
> überladene Funktionen übersichtlicher, weil kürzer. Das ist schon alles,
> was diese Syntax-Gimmicks bringen...

Ich finde, dass kompakter und übersichtlicher Quellcode durchaus ein 
erstrebenswertes Ziel ist.

> Da, wo tatsächlich geackert wird, auf der Ebene der Hardware, bringt das
> garnix. Es ist eher so, dass durch diese beschwingte Leichtigkeit auf
> der abgehobenen Ebene des Hochsprachencodes die Tendenz steigt, Code,
> den man tatsächlich vereinheitlichen könnte, nicht wirklich zu
> vereinheitlichen, sondern immer und immer wieder zu PHYSISCH zu
> manifestieren.

Das gilt nur, wenn man nicht weiß, was man tut. Es ist eben wie mit 
jedem Werkzeug: Wenn man nicht damit umgehen kann, wird man damit auch 
keine guten Ergebnisse erzielen.

von c-hater (Gast)


Lesenswert?

Rolf M. schrieb:

> Das gilt nur, wenn man nicht weiß, was man tut. Es ist eben wie mit
> jedem Werkzeug: Wenn man nicht damit umgehen kann, wird man damit auch
> keine guten Ergebnisse erzielen.

Tja, womit wir zum Kern des Problems kommen: Ganz offensichtlich können 
die meisten C++-Programmierer mit ihrem Werkzeug halt nicht umgehen und 
erzielen deshalb nur eher bescheidene Ergebnisse...

Wie schon gesagt: jede größere Anwendung für den PC enthält unzählige 
Beispiele dafür. Und es werden mit jeder Version derselben Software 
mehr. Das ist inzwischen so signifikant, dass man nicht mal mehr den 
Code analysieren muss, es reichen Mustererkennung und statistische 
Methoden zur Auswertung. Mal ganz abgesehen von dem Sachverhalt, dass es 
fühlbar und messbar immer langsamer wird, dieselben Sachen zu tun, die 
man auch früher mit dem Vorläufer derselben Software getan hat...

Ich behaupte: Es liegt daran, weil sie (also die Programmierer) nie 
gelernt haben, zu verstehen, was da zur Laufzeit wirklich passiert, wenn 
sie diesen Kram benutzen. Nicht zuletzt etliche Beiträge in diesem 
Thread hier beweisen das wirklich eindringlichst...

von Programmierer (Gast)


Lesenswert?

c-hater schrieb:
> Wie schon gesagt: jede größere Anwendung für den PC enthält unzählige
> Beispiele dafür.

Dann zeig mir doch mal eine PC-Anwendung und 3 dieser unzähligen 
Beispiele, wo templates die Performance gegenüber einer templatelosen 
Alternative signifikant beeinträchtigen.

c-hater schrieb:
> Ich behaupte: Es liegt daran, weil sie (also die Programmierer) nie
> gelernt haben, zu verstehen, was da zur Laufzeit wirklich passiert, wenn
> sie diesen Kram benutzen.

Nicht jeder Programmierer der Welt hat den Luxus, das alles ausführlich 
zu lernen. So viele Hochschulen gibt es gar nicht. Und so viel sind die 
Kunden gar nicht bereit für durch hochqualifiziertes Personal erstellte 
Software zu zahlen - ob Cash, Werbung oder Nutzerdaten.

von Stefan F. (Gast)


Lesenswert?

c-hater schrieb:
> Tja, womit wir zum Kern des Problems kommen: Ganz offensichtlich können
> die meisten C++-Programmierer mit ihrem Werkzeug halt nicht umgehen und
> erzielen deshalb nur eher bescheidene Ergebnisse...

Du wieder mit deinen Verallgemeinerungen.

Wenn die meisten C++ Programmierer unfähig wären, würde man heute nicht 
immer noch so viel in C++ schreiben. Denn die Entscheider hätten 
aufgrund der schlechten Ergebnisse auf etwas anderes gewechselt.

von Carl D. (jcw2)


Lesenswert?

Stefan ⛄ F. schrieb:
> c-hater schrieb:
>> Tja, womit wir zum Kern des Problems kommen: Ganz offensichtlich können
>> die meisten C++-Programmierer mit ihrem Werkzeug halt nicht umgehen und
>> erzielen deshalb nur eher bescheidene Ergebnisse...
>
> Du wieder mit deinen Verallgemeinerungen.
>
> Wenn die meisten C++ Programmierer unfähig wären, würde man heute nicht
> immer noch so viel in C++ schreiben. Denn die Entscheider hätten
> aufgrund der schlechten Ergebnisse auf etwas anderes gewechselt.

Das Problem ist, das er gar nicht gemerkt hat, daß seine Argumentation 
das genau konträre Ergebnis belegt. Nur eben nicht, wenn man jedes 
Argument als Beleg für die eigene "Wahrheit" sieht.

von Einer K. (Gast)


Lesenswert?

Carl D. schrieb:
> er gar nicht gemerkt

Für mich ist die Sache klar!

Behauptungen, ohne Belege.
So tun, als wäre es Wahrheit.
Ist Lüge.
Niederträchtige Lüge und Diffamierung.

Fachlich blitzt ja bei unserem C-Hasser manchmal was auf.
Aber ansonsten, sein Sozialverhalten, ist hier unter aller Sau.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.