所以,这基本上就是我想要做的:
#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”条件下使用参数的名称,就像字符串一样。这就是为什么我使用宏(具有 # 和 ## 特殊字符的良好特性)而不是模板函数的原因。
基本上,我需要一个纯文本转换(因此是一个宏,而不是一个函数),但带有参数的变量名。
让我们假设我有二十个不同的类,每一个都与另一个非常不同(例如,类 1 可以用两个 double 构造,类 2 需要一个 double 和两个整数,类 3 可以用两个构造 bool 等...)。
所有这些类都有一个“运行”成员函数,它产生相同格式的输出。
我的程序应该执行以下操作:
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 - 然后,在读取文件时,对于括号内的部分,我首先读取一个字符串(“标签”),然后读取“=”,最后读取值。该值将存储在与字符串同名的变量中
(如果我找到“speed = 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 () 是“字段”类的成员函数,如果不可用(即文件中不存在)则引发异常,否则返回值(从文件读取)。
“字段”类还有一个重载运算符 >>,它对值应用标准运算符 >>,并将 bool 属性设置为 true。
由于模型太多,我想在宏中转换代码:-)
最佳答案
我不确定您是否有像我将要提议的那样彻底改变您的实现的自由,但这是我会做的。它不需要任何奇特的模板技术。
首先,您创建一个名为 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 类型,您可以从中派生所有其他类型,如 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 构造函数会。
现在,您定义一个 Loader 类来处理解析。它包含一个返回 Base* vector 的成员 readFile,这样您就有了指向一个容器中所有已初始化对象的指针。我选择了 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");
}
}
};
希望这对您有所帮助。
关于c++ - 没有 __VA_ARGS__ 的可变参数宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21607655/
我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我有一个奇怪的问题:我在rvm上安装了rubyonrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option
我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano