2

私はProtoを使って、幾何学的ベクトルを操作するDSELを構築しようとしています。割り当て式を受け取り、コンポーネントごとに展開する変換を作成しようとしています。たとえば、私は置き換えたい

p = q + r;

p[0] = q[0] + r[0],
p[1] = q[1] + r[1],
...,
p[N] = q[N] + r[N],
p;

これまでのところ、変換と組み合わせて、各ベクトルコンポーネントの式を再帰的に展開する変換テンプレートを作成することで、ほとんどの場合それを機能させることができました。unroll_vector_exprdistribute_subscript

boost::result_ofとで使用される「パラメータ」の論理的根拠が何であるか理解していないようですresult_of::make_expr。ドキュメント、例、内部コードが混在しているようですExpr、、。何をいつ使用すれば、実際の結果タイプと一致するのかわかりません。現在、エラーメッセージを調べ、との不一致を修正することで、エラーを試行して機能させました。ただし、式をディープコピーするとすぐに、ターミナルは参照によって保持されなくなり、コードが失敗します。impl::exprimpl::expr_paramresult_typeconst&

struct distribute_subscript
  : or_<
        scalar_grammar
      , when<
            vector_literal
          , _make_subscript( _, _state )
        >
      , plus< distribute_subscript, distribute_subscript >
      , minus< distribute_subscript, distribute_subscript >
      , multiplies< distribute_subscript, distribute_subscript >
      , divides< distribute_subscript, distribute_subscript >
      , assign< distribute_subscript, distribute_subscript >
    >
{};

template< std::size_t I, std::size_t N >
struct unroll_vector_expr_c;

template< std::size_t I, std::size_t N >
struct unroll_vector_expr_c
  : transform< unroll_vector_expr_c< I, N > >
{
    template< typename Expr, typename State, typename Data >
    struct impl
      : transform_impl< Expr, State, Data >
    {
        typedef
            typename result_of::make_expr<
                tag::comma
              , typename boost::result_of<
                    distribute_subscript(
                        Expr
                      , typename result_of::make_expr<
                            tag::terminal
                          , boost::mpl::size_t< I - 1 >
                        >::type
                    )
                >::type
              , typename boost::result_of<
                    unroll_vector_expr_c< I + 1, N >(
                        Expr
                    )
                >::type
            >::type
            result_type;

        result_type operator ()(
            typename impl::expr_param expr
          , typename impl::state_param state
          , typename impl::data_param data
        ) const
        {
            return
                make_expr< tag::comma >(
                    distribute_subscript()(
                        expr
                      , make_expr< tag::terminal >( 
                            boost::mpl::size_t< I - 1 >()
                        )
                    )
                  , unroll_vector_expr_c< I + 1, N >() (
                        expr
                    )
                );
        }
    };
};

template< std::size_t N >
struct unroll_vector_expr_c< N, N >
  : transform< unroll_vector_expr_c< N, N > >
{
    template< typename Expr, typename State, typename Data >
    struct impl
      : transform_impl< Expr, State, Data >
    {
        typedef
            typename boost::result_of<
                distribute_subscript(
                    Expr
                  , typename result_of::make_expr<
                        tag::terminal
                      , boost::mpl::size_t< N - 1 >
                    >::type
                )
            >::type
            result_type;

        result_type operator ()(
            typename impl::expr_param expr
          , typename impl::state_param state
          , typename impl::data_param data
        ) const
        {
            return
                distribute_subscript()(
                    expr
                  , make_expr< tag::terminal >( 
                        boost::mpl::size_t< N - 1 >()
                    )
                );
        }
    };
};

struct unroll_vector_expr
  : transform< unroll_vector_expr >
{
    template< typename Expr, typename State, typename Data >
    struct impl
      : transform_impl< Expr, State, Data >
    {
        typedef
            typename dimension<
                typename boost::remove_reference<
                    typename boost::result_of<
                        _value( State )
                    >::type
                >::type
            >::type
            dimension;

        typedef
            typename result_of::make_expr<
                tag::comma
              , typename boost::result_of<
                    unroll_vector_expr_c< 1, dimension::value >(
                        Expr
                    )
                >::type
              , State
            >::type
            result_type;

        result_type operator ()(
            typename impl::expr_param expr
          , typename impl::state_param state
          , typename impl::data_param data
        ) const
        {
            return
                make_expr< tag::comma >(
                    unroll_vector_expr_c< 1, dimension::value >()(
                        expr
                    )
                  , boost::ref( state )
                );
        }
    };
};

からの結果とresult_type一致し、値と参照の両方で保持されるように変換を作成するにはどうすればよいですか?operator ()terminal

更新: Ericの回答後にコードが更新されました。result_typeとの間で残っている唯一の不一致make_exprは、の最初のインスタンス化に対するものですunroll_vector_expr_c。ここで、はではなくconst参照terminal< mpl::size_t< 0 > >::typeによって保持されます。不思議なことに、同じテンプレートをより高いインデックスでインスタンス化しても、この問題は発生しません。

更新distribue_subscript:変換を変更して添え字インデックスを値で強制的に取得した後、コードを完全に機能させることができました:

struct distribute_subscript
  : or_<
        scalar_grammar
      , when<
            vector_literal
          , _make_subscript( _, _byval( _state ) ) // <-- HERE
        >
      , plus< distribute_subscript, distribute_subscript >
      , minus< distribute_subscript, distribute_subscript >
      , multiplies< distribute_subscript, distribute_subscript >
      , divides< distribute_subscript, distribute_subscript >
      , assign< distribute_subscript, distribute_subscript >
    >
{};
4

1 に答える 1

3

今のところ簡単な答え。明日はあなたの変身をもっと詳しく見ていきます。

との意味はimpl::expr、のimpl::expr_paramドキュメントを参照することで理解できますtransform_impl。つまり、関数に渡されたときに式がコピーされないようにするためにを追加するためimpl::expr_param、トランスフォームのシグニチャで使用します。のように、型の計算に使用します。あまり役に立たないので無視してかまいません。operator()const &Exprboost::result_ofimpl::expr

deep_copy常に端末を価値によって保持することを強制することに関しては、それがほとんどの目的deep_copyです。deep_copyしかし、私はあなたのコードのどこにも見当たらないので、多分あなたは何か他のものを意味します。

についての一言make_expr:どのノードを参照によって、どのノードを値によって保存するかについて、非常に慎重に考える必要があります。型計算(result_of::make_expr)では、参照型は参照によって保持される必要があるものですが、実際の関数呼び出し(proto::make_expr)では、必要に応じて、参照によって保持される必要がある場合は、物をラップする必要がありboost::refます。これは変です。のユーザードキュメントを確認してくださいmake_expr

于 2012-10-31T05:27:17.963 に答える