Forum: PC-Programmierung Reflexion in Standard C++


von ManuelGast (Gast)


Lesenswert?

Hallo zusammen,


Was heisst Rfelexion in C++ und wofür soll gut sein?
Der Begriff kenne ich von Java aber in C++ kenne ich gar nicht.
Wie verwendet man das?

Danke in voraus

von C. A. Rotwang (Gast)


Lesenswert?

ManuelGast schrieb:

> Was heisst Rfelexion in C++ und wofür soll gut sein?

Da haben sich schon die passenden Fachidiots an anderer Stelle drüber 
ausgelassen:

https://www.c-plusplus.net/forum/106672-full

Ich hab dergleichen nie gebraucht, vermisse es aber nicht. Wozu soll das 
gut sein und hält es was es verspricht?

von Sebastian V. (sebi_s)


Lesenswert?

ManuelGast schrieb:
> Wie verwendet man das?

Bis jetzt nocht gar nicht, da daran noch gearbeitet wird.

C. A. Rotwang schrieb:
> Ich hab dergleichen nie gebraucht, vermisse es aber nicht. Wozu soll das
> gut sein und hält es was es verspricht?

Nur um mal ein einfaches Beispiel zu nennen, dass nicht gleich 
Templateprogrammierung erfordert: Konvertieren von Enum Werten zu 
Strings mit dem Namen des Enum Werts. Bis jetzt kann man da nur 
irgendwas mit Macros zusammen basteln oder man schreibt es von Hand.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

C. A. Rotwang schrieb:

> Ich hab dergleichen nie gebraucht, vermisse es aber nicht. Wozu soll das
> gut sein und hält es was es verspricht?

Ja, oder wie man in Norddeutschland sagt: "Wat de Bur nicht kennt, dad 
frit hey nicht" ;-)

Anderes Beispiel wäre Serialisierung.

von ManuelGast (Gast)


Lesenswert?

Mir ist immer nicht klar wofür ist das gut? und wofür verwendet man das?
Was gewinnt man daraus?

Grund warum ich frage: gestern habe ich einen Vorstellungsgespräch 
gehabt und der Typ fragt mich, ob ich Reflection kenne?
dann habe ich gesagt ja, der Begriff ist mir bekannt in Java aber in 
Standard C++ kenne ich nicht und habe ne benutzt.
Dann sagte mir doch das gibt schon in C++ .....


ich verstehe immer noch wie und wofür ist das gut?

von Dumdi D. (dumdidum)


Lesenswert?

ManuelGast schrieb:
> ich verstehe immer noch wie und wofür ist das gut?

Immer wenn Du zur Laufzeit Informationen braychat die nur den Conpiler 
vorliegen.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

ManuelGast schrieb:
> Mir ist immer nicht klar wofür ist das gut? und wofür verwendet man das?
> Was gewinnt man daraus?

Du hast Deinem Gesprächspartner erzählt, Du kennst Reflection aus Java, 
weist aber nicht, wofür man das verwenden kann?

> Grund warum ich frage: gestern habe ich einen Vorstellungsgespräch
> gehabt und der Typ fragt mich, ob ich Reflection kenne?
> dann habe ich gesagt ja, der Begriff ist mir bekannt in Java aber in
> Standard C++ kenne ich nicht und habe ne benutzt.
> Dann sagte mir doch das gibt schon in C++ .....

Der derzeitige Support für reflection in C++ ist relativ dürftig (man 
korregiere mich, wenn ich flasch liege). In C++ kannst Du z.B. auf eine 
feste Reihenfolge von Typen zugreifen. Du kannst ermitteln, ob A von B 
erbt. Du kannst aber nicht ermitteln, welche Basisklassen eine Klasse 
hat.

> ich verstehe immer noch wie und wofür ist das gut?

Mit reflection kannst Du auf im Algemeinen auf Informationen zu 
Datentypen zugeifen. Z.b. welche Member eine Klasse hat, welche Typen 
und Namen die haben etc. Also, die Möglichkeit, der Software über sich 
selbst zu Reflektieren.

Sebastian hat als Beispiel z.B. Stringkonvertierungsfunktionen für Enums 
aufgeführt. Die könnte man sehr generisch implementieren, wenn man mit 
reflection ermitteln könnte, wie viele member ein enum hat und wie die 
heisen und welche Werte die haben.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Hier noch ein interessanter Blogpost von Jacki Kay zum Thema: 
http://jackieokay.com/2017/04/13/reflection1.html

von Sven B. (scummos)


Lesenswert?

Der Qt Meta Object Compiler fügt einiges an Reflection zu C++ hinzu.

von Daniel A. (daniel-a)


Lesenswert?

Ich bilde in C manchmal reflection mittels Macros nach. z.B. so:
1
#define ANIMALS \
2
  X(fox) \
3
  X(cat) \
4
  X(wulf)
5
6
#define X(Y) #Y,
7
const char* animal_list[] = {ANIMALS};
8
#undef X
9
10
#define X(Y) Y,
11
enum animal_constants {ANIMALS animal_count};
12
#undef X
wird zu:
1
const char* animal_list[] = {"fox", "cat", "wulf",};
2
enum animal_constants {fox, cat, wulf, animal_count};

So kann man einfach den Namen der Constante herausfinden: 
animal_list[fox] wäre "fox".
Man kann auch durch alle Werte durchiterieren: for(size_t 
animal=0;animal<animal_count;animal++);
animal ist dann jeweis der Index, und somit der Wert der Constante, und 
animal_list[animal] wäre der Name der Constante als string. So könnte 
man also auch vom String "cat" den Index in animal_list herausfinden und 
damit den Wert der Constante cat ermitteln.

Ein anderes Beispiel wäre das Generieren von Parser code zum Einlesen 
von Werten in structs. Das habe ich z.B. bei diesem Projekt angewendet: 
https://github.com/Daniel-Abrecht/unitscript/blob/98b482270f9b1f2d5416b6c347af3b44d940866d/template/unitscript.template#L37
Ich binde einfach das Template ein, und der "yamlparser.generator" 
expandiert aus dem PARSABLE_STRUCTURES macro ein Struct und parser 
Funktionsdeklarationen. Wenn ich das Template aber mit 
-DUS_GENERATE_CODE compiliere, expandiert yamlparser.generator das 
PARSABLE_STRUCTURES macro in yaml parser code. Dies erspart mir 
haufenweise redundanten Code zu schreiben, und wenn ich eine andere 
Structur oder einen neuen Eintrag hinzufügen will, kann ich einfach 
einen BLOCK() oder ENTRY() zum PARSABLE_STRUCTURES macro hinzu, und muss 
nichts am parser code herumbasteln.

Dies sind die einzigen nützlichsten Anwendungsfälle, die ich bisher 
hatte, wo reflection nützlich gewesen wäre. Als C++ feature fände ich es 
deshalb praktisch, wenn es compile time reflektion gebe mit der man Code 
generieren kann. Eine art Generator template, mit dem man durch 
Strukturmember hindurchiterieren kann, und je nach Membereigenschaften 
code generieren könnte. Irgendetwas in die richtung:
1
template<struct A>
2
namespace MyParser {
3
  A parse(std::string str){
4
    A a;
5
    A:each(member) {
6
      IfTypeEqual<member::type,int>::value:expand {
7
        a.<member> = atoi(str);
8
      }
9
    }
10
    return a;
11
  }
12
}
13
14
struct MyStruct {
15
  int x;
16
}
17
18
MyParser<MyStruct> MyStructParser;
19
20
int main(){
21
  auto a = MyStructParser::parse("123");
22
  std::cout << a.x << std::endl;
23
}

Soetwas in die richtung wäre wohl auch in C++20 möglich, aber ich glaube 
dort wird soetwas unnötig verkompliziert. Ausserdem finde ich runtime 
reflection überflüssig und überhaupt eine schlechte Idee.

von Scott Meyers (Gast)


Lesenswert?

Es gibt derzeit kein wirkliches Reflection in C++, es gibt aber einen 
Vorschlag für C++20:

https://www.meetingcpp.com/blog/items/reflections-on-the-reflection-proposals.html

https://www.youtube.com/watch?v=4AfRAVcThyA

Was derzeit möglich ist, ist gewissermaßen eine "passive" Reflection 
über das Detection-Idiom bzw. SFINAE. Allerdings muss man da eben schon 
wissen, nach was man "sucht" (deswegen passiv). Eine 
Laufzeit-Enumeration aller bspw. Member geht derzeit nicht.

von C. A. Rotwang (Gast)


Lesenswert?

Torsten R. schrieb:
> Hier noch ein interessanter Blogpost von Jacki Kay zum Thema:
> http://jackieokay.com/2017/04/13/reflection1.html

Zitat:
"I believe reflection is an indispensible tool for generic libraries and 
huge frameworks that deal with lots of different types and complex 
relationships between those types"

Im embedded-Bereich also Mikrocontroller gibt es eher wenige typen und 
deren Beziehung zueinander ist simple. Die benutzten Bisbliotheken würde 
ich jetzt auch nicht als "huge" bezeichnen. Kann man also davon ausgehen 
das in diesem Bereich reflections eher wenig von Vorteil für den 
Anwendungsprogrammierer sind?

Welche Nachteile birgt eine reflections Implementierung in C++? Um 
welchen Faktor wird die erzeugte objectdatei aufgebläht?

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

C. A. Rotwang schrieb:

> Welche Nachteile birgt eine reflections Implementierung in C++? Um
> welchen Faktor wird die erzeugte objectdatei aufgebläht?

Ich denke, dass beide, bis jetzt genannten Beispiel (enum zu Text und 
Serialisierung) durch eine generische Implementierung nicht größer 
werden würden, als wenn Du das für jeden verwendeten Typen von Hand 
schreibst.

Das hängt aber natürlich vom zu Lösenden Problem und von der Lösung ab.

: Bearbeitet durch User
von Rolf M. (rmagnus)


Lesenswert?

Qt bietet für alle Klassen, die von QObject abgeleitet sind, und einige 
zusätzliche Typen sowas wie reflection. Dort wird aber der Meta Object 
Compiler verwendet, um diese Informationen zu generieren.

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.