在我的解释器中绑定嵌套函数的更好方法

时间:2012-01-22 00:08:32

标签: c++ boost bind

我正在尝试编写一个解释器来转换字符串:

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);函数只是将相关的标记传递给上面的相应函数。

1 个答案:

答案 0 :(得分:0)

请勿使用boost::functionboost::bind。您无法将boost::function传递给需要int的内容。

由于您只需要一种延迟参数,并且需要将其传递给所有函数,因此滚动自己的函数对象要容易得多。


使用boost::functionboost::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*参数。

相关问题