For a parser I'm developing I am parsing an event log. In the log, each line is an event, which makes it easy to parse the file line by line. The events that are logged have a string identifier at the start which is constructed like so:
X_Y_Z
X is always is the same, and can be parsed as a class with 8 members, as it has 8 arguments.
Y can be 6 different types, all of which have a different amount of parameters which can be interpreted differently depending on what type of Y they are. Creating a class for each of these 6 types is trivial; as they are just strings, ints and bools.
Z can be more than 20 different things, all with a different amount of parameters that can be interpreted differently. Creating a class for these 20+ types is also trivial; as they are just strings, ints and bools.
As such, an event class could be defined as so:
template<typename Y, typename Z>
struct Event {
DateTime timestamp;
X base;
Y prefix;
Z suffix;
}
This would allow us to construct 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 which I need. Furthermore, I would like to avoid casts where I can.
Important to note is that I need to iterate over these composed events after parsing is done, as a second pass of sorts.
What would be the most elegant way to achieve this?
Edit: One solution I have thought of would be to use std::variant, and storing the Y and Z as an integer based ID in the event class. It could work, but I am looking for something perhaps more elegant than a std::variant with 20 arguments.