11447


boost::mpl::accumulate や fold のネストはどうやったら実装できますか。

[code]

    namespace mpl=boost::mpl;
    
    typedef mpl::vector<mpl::int_<1>,mpl::int_<1>,mpl::int_<1>,mpl::int_<1>> vec1;
    typedef mpl::vector<mpl::int_<2>,mpl::int_<2>,mpl::int_<2>,mpl::int_<2>> vec2;
    typedef mpl::vector<mpl::int_<3>,mpl::int_<3>,mpl::int_<3>,mpl::int_<3>> vec3;
    typedef mpl::vector<vec1,vec2,vec3> vvec;
    
    typedef typename mpl::lambda
            <mpl::accumulate
                <mpl::_1 ,mpl::int_<0> ,mpl::plus<mpl::_1,mpl::_2> >
            >::type lam;
    
    typedef typename mpl::accumulate
        <vvec
        ,mpl::int_<0>
        ,mpl::plus<mpl::_1,lam::template apply<mpl::_2>::type>
        >::type result;
    
[/code]

このコードはコンパイルが通りませんでした。


CC BY-SA 3.0
2015-06-10T08:59:30.100
11217
2015-06-17T15:44:04.823
2015-06-10T13:13:41.883
3639
9247
question
c++ boost
boost::mpl::accumulate のネスト


[Placeholder
Expression](http://www.boost.org/doc/libs/1_50_0/libs/mpl/doc/refmanual/placeholder-
expression.html)に対して、`type`を使うと、placeholderにplaceholderの番号を代入してメタ式を評価してしまいます。

また、lambdaの中にメタ式をネストしてplaceholderを使う場合、placeholderには、一番近いlambdaのメタ引数が束縛されてしまいます。その結果、lambdaの中のplus式にメタ値が代入されてしまって、これはもはや式ではないので、accumulateの評価の際に、第三メタ引数にメタ式ではなくメタ値があるのでエラーになるのだと思います。  
これを防ぐためには、plusを別のlambdaで囲んで、外側のlambdaのメタ引数が束縛されないようにします。

以上を考慮すると以下の様にコードを修正すれば良いです。

[code]

    #include <boost/mpl/int.hpp>
    #include <boost/mpl/placeholders.hpp>
    #include <boost/mpl/apply.hpp>
    #include <boost/mpl/vector.hpp>
    #include <boost/mpl/lambda.hpp>
    #include <boost/mpl/accumulate.hpp>
    #include <boost/mpl/plus.hpp>
    
    #include <iostream>
    
    using namespace boost;
    
    typedef mpl::vector<mpl::int_<1>,mpl::int_<1>,mpl::int_<1>,mpl::int_<1>> vec1;
    typedef mpl::vector<mpl::int_<2>,mpl::int_<2>,mpl::int_<2>,mpl::int_<2>> vec2;
    typedef mpl::vector<mpl::int_<3>,mpl::int_<3>,mpl::int_<3>,mpl::int_<3>> vec3;
    typedef mpl::vector<vec1,vec2,vec3> vvec;
    
    typedef typename mpl::lambda<
        mpl::accumulate<
            mpl::_1, mpl::int_<0>, mpl::lambda<mpl::plus<mpl::_1, mpl::_2>>::type
        >
    >::type lamb;
    
    typedef typename mpl::accumulate<
        vvec
      , mpl::int_<0>
      , mpl::plus<mpl::_1, lamb::apply<mpl::_2>>
    >::type result;
    
    
    int main ()
    {
        static_assert(result::value == 24, "");
    }
    
[/code]

上記のコードではテンプレートの`>>`等のC++11 specificな文法が一部使われているので、C++03でコンパイルする際は適切に変更してください。


CC BY-SA 3.0
2015-06-17T15:38:40.527
11447
2015-06-17T15:44:04.823
2015-06-17T15:44:04.823
9968
9968
11217
answer