我正在尝试编写一个解释器来转换字符串:
vector(random(0, 1), 2, 3)
使用boost::bind
加入绑定函数,如:
bind(&vector, bind(&random, 0, 1), 2, 3)
预期的用途是用于粒子系统,所以我希望能够将粒子传递给这些粒子,这是通过添加一个lambda来实现的:
bind(&vector, bind(&random, 0, 1, _1), 2, 3, _1)
然后将这些绑定函数定义为:
typedef boost::function<boost::any(Particle*)> bound_particle_func;
所以我可以形成一种函数调用列表,将每个粒子传递给这个列表来操纵它们的行为,从而创建一个效果。
我可以很容易地让解释器像vector(1, 2, 3)
那样处理,但是当涉及到嵌套函数时,事情变得越来越混乱,我觉得我很蠢。
因为解析器当前以递归方式处理嵌套函数,所以我不能直接将lambda值绑定到嵌入式函数。
所以而不是最终结果
bind(&vector, bind(&random, 0, 1, _1), 2, 3, _1)
我实际上最终得到了
bind(&vector, bound random function, 2, 3, _1)
没有通过粒子的绑定函数。
我不知道如何更好地处理嵌套函数。
我目前的实际代码(不可编译)是:
typedef std::vector<Token>::iterator token_it;
typedef boost::function<boost::any(Particle*)> bound_particle_func;
Vector3 vector(float x, float y, float z, Particle* p = 0);
bound_particle_func parse(token_it& it);
bound_particle_func ParseVector(std::vector<Token>& tokens) {
const static int arg_count = 3;
std::vector<boost::variant<float, bound_particle_func>> args(arg_count);
int type[] = { 0, 0, 0 };
for(token_it it = tokens.begin(); it != tokens.end(); ++it) {
Token& t = *it;
if(t.type == Type::FLOAT) {
args.push_back(t.float_value);
} else if(t.type == Type::FUNCTION) {
args.push_back(parse(it));
type[args.size() - 1] = 1;
} else {
throw std::runtime_error("Type error: expected float");
}
if(args.size() > arg_count) {
throw std::runtime_error("Too many arguments for function `vector`");
}
}
return boost::bind(&vector, (type[0] == 0 ? boost::get<float>(args[0]) : boost::get<bound_particle_func>(args[0])),
(type[1] == 0 ? boost::get<float>(args[1]) : boost::get<bound_particle_func>(args[1])),
(type[2] == 0 ? boost::get<float>(args[2]) : boost::get<bound_particle_func>(args[2])),
boost::lambda::_1);
}
bound_particle_func parse(token_it& it);
函数只是将相关的标记传递给上面的相应函数。
答案 0 :(得分:0)
请勿使用boost::function
或boost::bind
。您无法将boost::function
传递给需要int
的内容。
由于您只需要一种延迟参数,并且需要将其传递给所有函数,因此滚动自己的函数对象要容易得多。
使用boost::function
和boost::bind
的替代方法是使用类似的内容:
Vector3 f_vector(bound_particle_func x, bound_particle_func y,
bound_particle_func z, Particle* p = 0)
{
return vector (boost::get<float>(x(p)), boost::get<float>(y(p)),
boost::get<float>(z(p)), p);
}
同样适用于您的其他功能。数字由绑定函数表示,这些函数只返回其绑定的float
参数并忽略它们的Particle*
参数。