Compiling a class of multiple classes in C ++ at runtime

For the analyzer that I am developing, I am parsing the event log. In the log, each line is an event that makes it easy to analyze the file line by line. Events that are logged have a string identifier at the beginning, which is constructed as follows:

X_Y_Z 

X always the same and can be parsed as a class with 8 members, since it has 8 arguments.

Y can be 6 different types, all of which have a different number of parameters that can be interpreted differently depending on the type of Y Creating a class for each of these 6 types is trivial; since they are just string s, int and bool s.

Z can be more than 20 different things, all with a different number of parameters that can be interpreted in different ways. Creating a class for these 20+ types is also trivial; since they are just string s, int and bool s.

Thus, an event class can be defined as follows:

 template<typename Y, typename Z> struct Event { DateTime timestamp; X base; Y prefix; Z suffix; } 

This would allow us to build any possible combination of events at compile time.

The problem is that the log file is parsed at runtime, and I would like to be able to compose these classes at runtime, depending on what I need. In addition, I would like to avoid throws where I can.

It is important to note that I need to iterate over these arranged events after the parsing is complete, as a second pass.

What will be the most elegant way to achieve this?

Change One solution I was thinking about would be to use std::variant and keep Y and Z as an identifier based on an integer in the event class. It may work, but I'm looking for something more elegant than std::variant with 20 arguments.

+5
source share
1 answer

If polymorphism-based solutions are viable, you can use dual dispatch methods to do this.
It follows a minimal working example showing how it can work:

 struct X { int i; int j; }; struct Visitor; struct YBase { virtual void accept(Visitor &) =0; }; struct Y1: YBase { void accept(Visitor &) override; int i; }; struct Y2: YBase { void accept(Visitor &) override; bool b; }; struct ZBase { virtual void accept(Visitor &) = 0; }; struct Z1: ZBase { void accept(Visitor &) override; double d; }; struct Z2: ZBase { void accept(Visitor &) override; char c; }; struct Visitor { void visit(Y1 &y1) { y1.i = 0; } void visit(Y2 &y2) { y2.b = true; } void visit(Z1 &z1) { z1.d = .42; } void visit(Z2 &z2) { z2.c = 'c'; } }; void Y1::accept(Visitor &v) { v.visit(*this); } void Y2::accept(Visitor &v) { v.visit(*this); } void Z1::accept(Visitor &v) { v.visit(*this); } void Z2::accept(Visitor &v) { v.visit(*this); } struct Event { X base; YBase *prefix; ZBase *suffix; }; void visit(Event &e) { Visitor v; e.prefix->accept(v); e.suffix->accept(v); } int main() { Y2 y; Z1 z; Event e; e.prefix = &y; e.suffix = &z; visit(e); } 

For I do not know what the real problem is in the details, I did my best to give you a meaningful example. I suppose you can use the visitor class to extract the parameters of interest from the erased instances of Y* / Z* .
In any case, this can be used as a point from which you can start developing your own solution based on dual scheduling.

0
source

Source: https://habr.com/ru/post/1270370/


All Articles