Reflexion in Standard C++

#5229175
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.
Gast #5229208
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?
(Firma: Torrox.de) #5229230
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.
#5229648
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.
Gast #5229690
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.
Gast #5231652
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?
(Firma: Torrox.de) #5231666
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren