Variadic Macro without __VA_ARGS__
Variadic Macro without __VA_ARGS__
所以,这基本上就是我要做的:
#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);}
这是三个参数的情况,但我也需要:
#define RS04(obj, a1, a2, a3, a4)
#define RS05(obj, a1, a2, a3, a4, a5)
#define RS06(obj, a1, a2, a3, a4, a5, a6)
...
所以一个变异的宏。
关于此类主题的Stackoverflow有许多问题,但它们不适用于我的案件。
在上面的代码中,三个参数a1,a2和a3既用作字符串(在" if"条件)和变量(在分配和构造函数中),而obj是一类(因此宏中的最后命令是构造函数调用)。
关键是:假设我有二十个不同的类,每个类都需要一个不同的输入才能构造。
宏接收类的名称和构建此类对象所需的参数的名称。
关键是(请参阅下面的"设计原因"),我需要在" if"条件下使用参数的名称。这就是为什么我使用宏(具有#和##特殊字符的不错功能)而不是模板函数的原因。
基本上,我需要一个纯文本转换(因此是宏,而不是函数),但是有一个可变的参数名称。
此设计的原因
让我们假设我有二十种不同的类,一个与另一个类别有很大不同(例如,可以用两个双double构建1类布尔等...)。
所有这些classe都具有"运行"成员函数,该功能产生相同格式的输出。
我的程序应执行以下操作:
1-阅读文本文件
2-启动文件中描述的每个模型的运行
文件应该是这样的:
car {
name = model1
speed = 0.05
}
man {
name = model2
speed = 0.03
male = true
ageclass = 3
}
...
所以我需要读取此类文件并初始化文件中描述的每个类。
参数应以用户喜欢的任何顺序编写。
另外,它们可能出现多次,例如:
car {
name = pippo
speed = 0.05
speed = 0.06
speed = 0.07
}
(在这种情况下,最后一个将覆盖另一个)
如果用户忘记了一些参数,则程序应停止使用明确的错误消息。
可能有不同类型的模型(例如,4个不同的平面模型)。
例如,在这种情况下:
car {
name = pippo
speed = 0.05
}
car {
name = pluto
}
程序应该说第二个模型不完整。
当然有多种方法可以做到。
我以这种方式做:
1-创建一个模板类(我们将其称为"字段"),用t成员(存储一个值)和一个布尔成员(告诉我是否存在变量)
2-创建一个具有许多"字段"的对象(读取器,读取文件的对象),一个用于每个可能的模型属性(_name,_name,_speed,_male等。)
3-然后,在阅读文件时,对于括号内的部分,我首先读取一个字符串("标签"),然后读取" =",最后我读取该值。该值将以字符串的相同名称
存储在变量中(如果我找到了" speed = 0.03"行,我将在读者的字段中保存0.03)。
这应该是伪代码(可能有ERROS;仅出于说明目的):
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()是"字段"类的成员函数,如果不可用(即,在文件中不存在),或返回值(从文件中读取)。
类"字段"还具有超载的操作员>>,该操作员在值上应用标准运算符>>,并将其设置为true boolean属性。
由于模型太多了,我想在宏中进行代码: - )
我不确定您是否可以自由地像我要提出的那样大幅度地更改实现,但这是我要做的。它不需要任何异国情调的模板技术。
首先,您创建一个称为Properies
的结构(例如),其中包含任何类都可以抑制的所有属性。
struct Properties
{
enum Types
{
MAN,
CAR,
// and more
};
enum Gender
{
MALE, FEMALE
};
Types type;
string name;
double speed;
Gender gender;
int ageClass;
};
您可以看到,它还包含一个描述每种现有类型的enum
。
接下来,您定义了Base
-Type,从中您得出所有其他类型(例如Man
,Car
等)。
class Base
{};
class Man: public Base
{
string d_name;
Properties::Gender d_gender;
int d_ageClass;
double speed;
public:
Man(Properties const &properties)
{
// Set properties that apply to the "Man"-class
}
};
class Car: public Base
{
string d_name;
double d_speed;
public:
Car(Properties const &properties)
{
// Set properties that apply to the "Car"-class
}
};
每个类的构造函数都期望Properties
对象,从中提取适合它们的字段。例如,Car
构造函数不会检查gender
字段,而Man
构造函数 Will 。
现在,您定义了Loader
类,该类将处理解析。它包含一个成员readFile
,该成员返回Base*
的向量,以便您对一个容器中的所有初始化对象都有指示。我选择了shared_ptr
来处理所有权问题,但是您应该决定最适合您的应用程序。
class Loader
{
public:
static vector<shared_ptr<Base>> readFile(string const &fileName)
{
vector< shared_ptr<Base> > result;
ifstream file(fileName);
// Parse the file, creating a "Properties" object, called
// "props" here
while (file) // while EOF not reached.
{
Properties props = parse(file); // implement your parse
// routine, returning Properties.
switch (props.type)
{
case Properties::CAR:
result.push_back(shared_ptr<Base>(new Car(props)));
break;
case Properties::MAN:
result.push_back(shared_ptr<Base>(new Man(props)));
break;
// etc for all classes derived from Base
default:
throw string("error: unknown type");
}
}
};
希望这会有所帮助。
- 如何修复带有 clang 的参数'args'缺少默认参数的问题?
- CPPYY/CTYPES 将字符串数组作为 char* args[] 传递
- 如何使模板函数像 R f<void(int)>(args...)
- 怎么可能写 f( *this, std::forward<Args>(args)... ) 而 f 只用 F f 声明;
- 折叠表达式和参数包:static_assert 内 Args&& 和 Args 之间的区别
- 为什么我不能添加 && 到 Ret (Args...) &?
- Ret(&)(Args...)和Ret(Args...)&有什么区别?
- 什么是 'R(*pf)(void*, Args..)',函数指向方法的指针?
- VS2017模板专用化错误无法从'Class *(__cdecl *)(Args...)'转换为'Class *(__cdecl *)(Args...)'
- 在C++中,如何将参数添加到"Args&&... args"参数列表中?
- "auto o = SomeType(args)"而不是"SomeType o(args)
- C Typedef修复模板ARGS
- 作为参数的'char *args[]'和'char **argv'之间的差异
- 我希望通过使用模板元编程从变量ARGS中进行剥离参数
- C++:将 Args && ... _args传递到嵌套列表的正确方法?
- 声明类型包含未展开的参数包'Args'
- 编译时检查大小是否为..(args) 匹配来自 constexpr 函数的结果
- 名称和派生名称类之间的串联(作为模板args)
- boost ::绑定发送变量的回调args到回调函数
- 如何添加一个空格字符来触发 var args c++ execlp()