I've a lot of data and inside a loop I need to put a selection. Every entry is a physics event. In every event there is only one particle with its properties:
for (...) { // loop over entries in the data
if (not selection()) continue;
...
}
From the command line I select a particular type of particle to be considered, for example:
Options options = get_options(argc, argv);
enum ParticleType_type {ELE, PHO, ...}
cout << "particle: " << get_particle_name(options.particle_type);
for (entry in data) { // loop over data
// read variale like PDG, conv, ... for the entry
switch (options.particle_type)
{
case ELE: if (PDG != 11) continue; break;
case PHO: if (PDG != 22) continue; break;
case PHO_UNC: if (PDG != 22 or conv) continue; break;
case PHO_CONV: if (PDG != 22 or !conv) continue; break;
case PHO_1TRK: if (PDG != 22 or !conv or !is1trak) continue; break;
case PHO_2TRK: if (PDG != 22 or !conv or !is2trak) continue; break;
case PHOR1: if (PDG != 22 or !conv or !(r>0 and <=200) continue; break;
case PHOR2: if (PDG != 22 or !conv or !(r>200 and &l开发者_JAVA技巧t;=400) continue; break;
case PHOR3: if (PDG != 22 or !conv or !(r>400 and <=600) continue; break;
case PHOR4: if (PDG != 22 or !conv or !(r>600 and <=800) continue; break;
}
do_something();
if (isPhoton(options.particle_type)) // true for every PHO_XXX
{
if (options.particle_type in [PHORX])
{
int rbin = get_Rbin(options.particle_type) // PHOR1 -> 1, PHOR2 -> 2
...
}
...
}
}
cout << "output: " << get_file_name(options.particle_type) + ".out";
as you can see:
- is't a mess
- there are subcategories, for example
PHO_CONV
is aPHO
andPHO_1TRK
is aPHO_CONV
- every
ParticleType_type
has some properties, like the name, the file_name and more - now I need to double the categories like
PHORx
usingr
step of 100 and not 200. I want to parametrize the range in some way, probably using template argument somewhere - I need to cross the categories for example creating
PHOR1_1TRK
- (less relevant) I'm dominating by I/O. Presently if I want to process
PHO
andELE
I need to run twice, I want to do them at the same time
I think the best solution is to create one class for every ParticleType_type, and put function like get_file_name
as member functions. The problem is that class are not object so I can't pass them as an argument of a function: for example with enum
now I can write free function that take ParType_type
as an argument, but with classes I can't.
I want to create automatically parametric types, for example PHORX.
Can someone suggest some tecniques?
The Flyweight pattern might be useful for you here.
Instead of having an instance for each particle with an enum of its type, you would have one single instance of each particle type and a pointer to this instance for each particle of that type. The particle type would take a pointer to your particle struct for computations.
e.g.
// pseudocode!
ParticleA a;
ParticleB b;
struct ParticleData {
Particle * type;
int data;
} particles[] = {
{ &a, 5 },
{ &a, 7 },
{ &b, 4 },
// ...
};
for each( particle in particles ) {
particle->type->do_something(particle);
}
Creating classes (subclasses of a (possibly abstract) particle class) for each particle type looks like the right approach.
You wouldn't be passing a class to a function, you'd be passing an instance of that class.
Instead of writing separate classes for all your particles you could use a table-driven method (see e.g. here).
You would create a table which uses a ParticleType_type
as index to get a function pointer or boost::function
that does the particle-specific processing.
精彩评论