boost 函数和 lambda 来包装函数

发布于 2024-12-08 15:12:56 字数 621 浏览 0 评论 0原文

我想将这个简单的代码:转换

void setZComp(Imath::V3f& pt)
{
    pt.z = 0.0;
}

int myfunc()
{
    ...

    std::vector<Imath::V3f> vec(5,Imath::V3f(1.0,1.0,1.0));
    std::for_each(vec.begin(),vec.end(),boost::bind(&setZComp,_1));

    ...
}

为类似的代码,以便不在外部声明 setZComp 而是某种内联声明,

int myfunc()
{
    ...

    boost::function<double(Imath::V3f&)> f = (boost::lambda::_1 ->* &Imath::V3f::z = 0.0) ;
    std::for_each(vec.begin(),vec.end(),boost::bind(&f,_1));

    ...
}

我对 Boost Bind 和 Lambda 很陌生,我不知道这是否可以在某些情况下完成方式。显然上面的代码是行不通的。

I want to convert this simple code:

void setZComp(Imath::V3f& pt)
{
    pt.z = 0.0;
}

int myfunc()
{
    ...

    std::vector<Imath::V3f> vec(5,Imath::V3f(1.0,1.0,1.0));
    std::for_each(vec.begin(),vec.end(),boost::bind(&setZComp,_1));

    ...
}

to something like that, in order to not have setZComp declared outside but some sort of inline declaration

int myfunc()
{
    ...

    boost::function<double(Imath::V3f&)> f = (boost::lambda::_1 ->* &Imath::V3f::z = 0.0) ;
    std::for_each(vec.begin(),vec.end(),boost::bind(&f,_1));

    ...
}

I'm quite new to Boost Bind and Lambda and I don't know if this can be done in some way. Obviously the code above does not work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

初见你 2024-12-15 15:12:56

您使用大锤来敲碎坚果吗?有时,我认为使用普通的 for 循环并自己显式设置变量会更简单。这使得代码更容易阅读和维护。

typedef std::vector<Imath::V3f> V3fVector;
V3fVector vec(5,Imath::V3f(1.0,1.0,1.0));

for (V3fVector::iterator i = vec.begin(), iEnd = vec.end(); iEnd != i; ++i)
    i->z = 0.0;

尽管 boost bind 很有用,但它也是一种语法混乱,使简单的代码变得不可读。

Are you using a sledgehammer to break a nut? Sometimes, I think it is simpler to just use a normal for loop and set the variable explicitly yourself. This makes the code much easier to read and maintain.

typedef std::vector<Imath::V3f> V3fVector;
V3fVector vec(5,Imath::V3f(1.0,1.0,1.0));

for (V3fVector::iterator i = vec.begin(), iEnd = vec.end(); iEnd != i; ++i)
    i->z = 0.0;

As much as boost bind is useful, its also a syntactical mess that make simple code unreadable.

迟到的我 2024-12-15 15:12:56

如果您无法使用 C++11 lambda,则可以使用 boost::lambda::bind
因此,在您的情况下,如下所示:

boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0

一个完整​​的示例,因为我不知道您的内部结构:

struct S
{
    S():i(0){};
    int i;
};
int main()
{
    std::vector<S> vec;
    vec.push_back(S());

    std::for_each(vec.begin(), vec.end(), boost::lambda::bind(&S::i, boost::lambda::_1) = 5);
    std::cout << vec.front().i << std::endl; // outputs 5
    return 0
}

If you cannot use a C++11 lambda, then you can use boost::lambda::bind.
So in your case something like the following:

boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0

A full example since I don't know your internals:

struct S
{
    S():i(0){};
    int i;
};
int main()
{
    std::vector<S> vec;
    vec.push_back(S());

    std::for_each(vec.begin(), vec.end(), boost::lambda::bind(&S::i, boost::lambda::_1) = 5);
    std::cout << vec.front().i << std::endl; // outputs 5
    return 0
}
难得心□动 2024-12-15 15:12:56

您也可以考虑看看 boost::phoenix。我认为它是比 lambda 库更充实的 C++ 函数式编程实现。

You might also consider taking a look at boost::phoenix. I think it's a more fully fleshed out implementation of functional programming for c++ than the lambda library.

浅沫记忆 2024-12-15 15:12:56

成员变量作为目标部分中所述

指向成员变量的指针实际上并不是一个函数,但 [boost::lambda::bind] 函数的第一个参数仍然可以是指向成员变量的指针。调用此类绑定表达式会返回对数据成员的引用。

因此,要构造访问 z 成员的 lambda 表达式,您可以使用:

boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1)

返回的对象本身可以在其他表达式中使用。例如,

boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0

表示“获取第一个参数的 z 成员的 double 引用(类型 Imath::V3f&)并分配值0.0”。

然后,您可以将此 lambda 与 Boost.Function 和 std::for_each 结合使用:

boost::function<void(Imath::V3f&)> f = boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0;
std::for_each(vec.begin(), vec.end(), f);

作为参考,这里是一个完整的、可编译的示例:

#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <boost/function.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>

namespace Imath
{
class V3f
{
public:
    double x, y, z;

    V3f(double x_, double y_, double z_)
        : x(x_), y(y_), z(z_)
    {
    }

    friend std::ostream& operator<<(std::ostream& os, const V3f& pt) {
        return (os << '(' << pt.x << ", " << pt.y << ", " << pt.z << ')');
    }
};
}

int main()
{
    std::vector<Imath::V3f> vec(5, Imath::V3f(1.0, 1.0, 1.0));
    boost::function<void(Imath::V3f&)> f = boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0;
    std::for_each(vec.begin(), vec.end(), f);

    std::vector<Imath::V3f>::iterator it, end = vec.end();
    for (it = vec.begin(); it != end; ++it) {
        std::cout << *it << std::endl;
    }

    return EXIT_SUCCESS;
}

输出:

(1, 1, 0)
(1, 1, 0)
(1, 1, 0)
(1, 1, 0)
(1, 1, 0)

As explained in the section Member variables as targets:

A pointer to a member variable is not really a function, but the first argument to the [boost::lambda::bind] function can nevertheless be a pointer to a member variable. Invoking such a bind expression returns a reference to the data member.

So to construct a lambda expression that accesses the z member, you can use:

boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1)

The returned object can itself be used in other expressions. For example,

boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0

means "obtain the double ref to the z member of the first argument (type Imath::V3f&) and assign the value 0.0".

You can then use this lambda with Boost.Function and std::for_each:

boost::function<void(Imath::V3f&)> f = boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0;
std::for_each(vec.begin(), vec.end(), f);

For reference, here is a complete, compilable example:

#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <boost/function.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>

namespace Imath
{
class V3f
{
public:
    double x, y, z;

    V3f(double x_, double y_, double z_)
        : x(x_), y(y_), z(z_)
    {
    }

    friend std::ostream& operator<<(std::ostream& os, const V3f& pt) {
        return (os << '(' << pt.x << ", " << pt.y << ", " << pt.z << ')');
    }
};
}

int main()
{
    std::vector<Imath::V3f> vec(5, Imath::V3f(1.0, 1.0, 1.0));
    boost::function<void(Imath::V3f&)> f = boost::lambda::bind(&Imath::V3f::z, boost::lambda::_1) = 0.0;
    std::for_each(vec.begin(), vec.end(), f);

    std::vector<Imath::V3f>::iterator it, end = vec.end();
    for (it = vec.begin(); it != end; ++it) {
        std::cout << *it << std::endl;
    }

    return EXIT_SUCCESS;
}

Outputs:

(1, 1, 0)
(1, 1, 0)
(1, 1, 0)
(1, 1, 0)
(1, 1, 0)
ゝ偶尔ゞ 2024-12-15 15:12:56

如果您可以访问支持 C++11 的最新版本的 g++ 或 MSVC 2010,您可以执行以下操作:

int myfunc()
{
    ...

    std::for_each(vec.begin(),vec.end(),[](Imath::V3f& pt){ pt.z = 0.0; });

    ...
}

If you have access to a recent version of g++ with C++11 support, or MSVC 2010, you could do the following:

int myfunc()
{
    ...

    std::for_each(vec.begin(),vec.end(),[](Imath::V3f& pt){ pt.z = 0.0; });

    ...
}
第几種人 2024-12-15 15:12:56

如果你想使用 boost::lambda,我有时发现在包含 lambda 的行之前声明一个“指向成员的指针”变量会更干净,这样你就可以使用 ->* 运算符而不是使用升压::拉姆达::绑定。

然而,正如艾伦指出的,这里的简单循环可能是最简单的解决方案。使用 BOOST_FOREACH 使其变得更加简单。

这是 mkaes 示例实现的修改版本,它使用运算符 ->* 而不是绑定,并且还演示了如何使用 BOOST_FOREACH 作为替代方案。

#include <iostream>
#include <vector>
#include <boost/lambda/lambda.hpp>
#include <boost/foreach.hpp>

// I like to provide alternate names for the boost::lambda placeholders
boost::lambda::placeholder1_type& arg1 = boost::lambda::_1 ;
boost::lambda::placeholder2_type& arg2 = boost::lambda::_2 ;
boost::lambda::placeholder3_type& arg3 = boost::lambda::_3 ;

struct S
{
    S():i(0){};
    int i;
};

int main()
{
    std::vector<S> vec;
    vec.push_back(S());

    // Define this pointer-to-member so we can
    //  use it in the lambda via the ->* operator
    int S::* i = &S::i ;

    std::for_each(vec.begin(), vec.end(), &arg1->*i = 5);
    std::cout << vec.front().i << std::endl; // outputs 5

    // Alternatively, just use a simple foreach loop
    BOOST_FOREACH( S & s, vec )
    {
        s.i = 6 ;
    }
    std::cout << vec.front().i << std::endl; // outputs 6

    return 0 ;
}

If you want to use boost::lambda, I sometimes find it cleaner to declare a "pointer-to-member" variable immediately before the line that contains the lambda, which then allows you to use the ->* operator instead of using boost::lambda::bind.

However, as Alan pointed out, a simple loop here might be the simplest solution. Use BOOST_FOREACH to make it even simpler.

Here's a modified version of mkaes's sample implementation that uses operator ->* instead of bind, and it also shows how to use BOOST_FOREACH as an alternative.

#include <iostream>
#include <vector>
#include <boost/lambda/lambda.hpp>
#include <boost/foreach.hpp>

// I like to provide alternate names for the boost::lambda placeholders
boost::lambda::placeholder1_type& arg1 = boost::lambda::_1 ;
boost::lambda::placeholder2_type& arg2 = boost::lambda::_2 ;
boost::lambda::placeholder3_type& arg3 = boost::lambda::_3 ;

struct S
{
    S():i(0){};
    int i;
};

int main()
{
    std::vector<S> vec;
    vec.push_back(S());

    // Define this pointer-to-member so we can
    //  use it in the lambda via the ->* operator
    int S::* i = &S::i ;

    std::for_each(vec.begin(), vec.end(), &arg1->*i = 5);
    std::cout << vec.front().i << std::endl; // outputs 5

    // Alternatively, just use a simple foreach loop
    BOOST_FOREACH( S & s, vec )
    {
        s.i = 6 ;
    }
    std::cout << vec.front().i << std::endl; // outputs 6

    return 0 ;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文