So, this is basically what I want to do:
#define RS03(obj, a1, a2, a3) {if (_str1 == #a1) _file >> _##a1; if (_str1 == #a2) _file >> _##a2;if (_str1 == #a3) _file >> _##a3; obj (_##a1, _##a2, _##a3);}
This is the case of three arguments, but I also need:
#define RS04(obj, a1, a2, a3, a4)
#define RS05(obj, a1, a2, a3, a4, a5)
#define RS06(obj, a1, a2, a3, a4, a5, a6)
...
So a variadic macro.
There are a number of questions on Stackoverflow on such topic, but they do not apply to my case.
In the code above, the three parameters a1, a2 and a3 are used both as string (in the "if" condition) and as variable (in the assignments and in the constructor), while obj is a class (so the last command in the macro is a constructor call).
The point is that: suppose I have twenty different classes, requiring each of them a different number of input to construct.
The macro receive the name of the class and the names of the arguments required to build an object of this class.
The point is that (see "reason of the design" below) I need to use the name of the argument also like string in a "if" condition. This is the reason why I use a macro (which have the nice feature of the # and ## special characters) instead of a template function.
Basically, I need a plain text conversions (so a macro, not a function), but with a variable name of arguments.
Reason of this design
Let us suppose I have twenty different classes, each of one is very different from the other (for example, class 1 can be constructed with two double, class 2 requires a double and two integer, class 3 can be constructed with two bool, etc...).
All these classe have a "run" member function which produce an output of the same format.
My program should do the following:
1 - read a text file
2 - launch the run for each model described in the file
The file should be something like that:
car {
name = model1
speed = 0.05
}
man {
name = model2
speed = 0.03
male = true
ageclass = 3
}
...
So I need to read such file and initialize each class described in the file.
Parameters should be written in whatever order the user like.
Also, they may appear more than one time, for example:
car {
name = pippo
speed = 0.05
speed = 0.06
speed = 0.07
}
(in this case, the last will overwrite the other)
If the user forget some parameters the program should stop with a clear error message.
There may be different model of the same type (for example, 4 different flat model).
For example, in such situation:
car {
name = pippo
speed = 0.05
}
car {
name = pluto
}
The program should say that the second model is incomplete.
There are of course a number of ways to do that.
I do in this ways:
1 - create a template class (let's call it "field") with a T member (which store a value) and a bool member (which tell me if the variable is present or not)
2 - create an object (the reader, the object which read the file) with a number of "fields", one for each possible model attribute (_name, _speed, _male, etc..)
3 - then, while reading the file, for the portion within the brackets, I first read a string (the "label"), then I read the "=", and finally I read the value. The value will be stored in the variable with the same name of the string
(if I found the line "speed = 0.03", the I'll save 0.03 in the field _name of the reader).
This should be the pseudo-code (there may be erros; it's just for illustrating purpose):
if (car) {
while (str != "}") {
if (str == "speed") { _file >> _speed; _file >> _str; }
if (str == "male") { _file >> _male; _file >> _str; }
if (str == "ageclass") { _file >> _ageclass; _file >> _str; }
ERROR;
}
car (_speed.get (), _male.get (), _ageclass.get ());
}
get () is a member function of the "field" class, which raise an exception if not available (i.e., not present in the file), or return the value (read from file) otherwise.
Class "field" also has an overloaded operator >>, which apply the standard operator >> on the value, and set to true the boolean attribute.
As the models are so many, I'd like to trasform that code in a macro :-)