【发布时间】:2014-03-03 16:17:28
【问题描述】:
所以,这基本上就是我想要做的:
#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 是一个类(所以宏中的最后一个命令是构造函数调用)。
重点是:假设我有 20 个不同的类,每个类都需要不同数量的输入来构造。
宏接收类的名称和构建此类对象所需的参数名称。
重点是(参见下面的“设计原因”)我需要在“if”条件下使用参数的名称,就像字符串一样。这就是为什么我使用宏(具有 # 和 ## 特殊字符的优点)而不是模板函数的原因。
基本上,我需要一个纯文本转换(所以是一个宏,而不是一个函数),但需要一个变量名的参数。
这种设计的原因
假设我有 20 个不同的类,每个类都非常不同(例如,类 1 可以用两个 double 构造,类 2 需要一个 double 和两个整数,类 3 可以用两个构造布尔等...)。
所有这些类都有一个“运行”成员函数,它产生相同格式的输出。
我的程序应该执行以下操作:
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 成员(存储值)和一个 bool 成员(告诉我变量是否存在)
2 - 创建一个具有多个“字段”的对象(读取器,读取文件的对象),每个可能的模型属性(_name、_speed、_male 等)一个。
3 - 然后,在读取文件时,对于括号内的部分,我首先读取一个字符串(“标签”),然后读取“=”,最后读取值。该值将存储在与字符串同名的变量中
(如果我找到“速度 = 0.03”这一行,我将在阅读器的字段_name 中保存 0.03)。
这应该是伪代码(可能有错误,只是为了说明):
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。
由于模型太多,我想在宏中转换代码:-)
【问题讨论】:
-
Boost.Preprocessor 有这方面的工具。
-
不能使用(可变参数)模板解决这个问题吗?在处理 C++ 时,它们应该总是优先于宏。
-
@JorenHeit 不是真的(在这种情况下),请注意预处理器标记连接运算符的使用。
-
@Angew 所有这些宏都可能是糟糕(即不是纯 C++)设计的标志 ;-)
-
我将宏用作文本转换:我必须重复相同的代码大约二十次,但稍作修改。我想在一个位置编写代码,这样我就可以在一个位置进行编辑。我使用宏而不是函数是因为我在主题末尾已经解释过(我需要以两种不同的形式使用相同的变量)
标签: c++ c-preprocessor variadic