1

この単純なコードを変換したい:

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 にまったく慣れていないので、これが何らかの方法で実行できるかどうかわかりません。明らかに、上記のコードは機能しません。

4

6 に答える 6

2

ナッツを割るのにハンマーを使っていますか?場合によっては、通常の 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;

ブースト バインドは便利ですが、単純なコードを読めなくする構文上の混乱もあります。

于 2011-10-06T13:47:38.923 に答える
2

C++11 ラムダを使用できない場合は、使用できます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
}
于 2011-10-06T13:50:21.410 に答える
1

セクションターゲットとしてのメンバー変数で説明されているように:

メンバー変数へのポインターは実際には関数ではありませんが、[ ] 関数の最初の引数boost::lambda::bindはメンバー変数へのポインターになることができます。このようなバインド式を呼び出すと、データ メンバーへの参照が返されます。

したがって、zメンバーにアクセスするラムダ式を作成するには、次を使用できます。

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

返されたオブジェクト自体を他の式で使用できます。例えば、

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

は、「最初の引数 ( type )doubleのメンバーへの参照を取得し、値 0.0 を割り当てる」ことを意味します。zImath::V3f&

次に、このラムダを 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)
于 2011-10-06T14:21:01.870 に答える
1

また、boost::phoenix も検討してみてください。これは、ラムダ ライブラリよりも C++ 向けの関数型プログラミングのより完全に肉付けされた実装だと思います。

于 2011-10-06T14:03:03.620 に答える
0

C++11 をサポートする最新バージョンの 、または MSVC 2010 にアクセスできる場合g++は、次の操作を実行できます。

int myfunc()
{
    ...

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

    ...
}
于 2011-10-06T13:45:41.127 に答える
0

boost::lambda を使用する場合は、ラムダを含む行の直前に「メンバーへのポインター」変数を宣言する方がきれいな場合があります。これにより、boost を使用する代わりに ->* 演算子を使用できるようになります。 ::ラムダ::バインド。

ただし、Alan が指摘したように、ここでの単純なループが最も単純な解決策かもしれません。BOOST_FOREACH を使用して、さらにシンプルにします。

これは、バインドの代わりに operator ->* を使用する 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 ;
}
于 2011-10-09T05:44:00.503 に答える