1

既存のコード プロジェクトに遅延評価を導入しようとしています。プロジェクトのコアは基本的に、カスタム型を使用した大量の計算で構成されています (これは double のように機能しますが、バックグラウンドで追加の作業を行います)。

私たちの目標は、既存の式を最適化するために、boost proto を使用して遅延評価の概念を導入することです。

制限:

  • 既存の計算は変更できません
  • 使用される型は typedef によって定義されるため、型自体を置き換えることが可能です

簡単な概念実証を実装しようとしましたが、コードが意図したとおりに動作するように管理できませんでした。これまでに得たものは次のとおりです。

#include <boost/proto/proto.hpp>
#include <complex>
#include <iostream>

using namespace std;
using namespace boost;
using namespace boost::proto;

// The custom implemented Type
typedef std::complex<double> my_type;

// The Basic expression wrapper
template< typename Expr = proto::terminal< my_type >::type >
struct MyDoubleExpr
  : proto::extends< Expr, MyDoubleExpr< Expr >, proto::default_domain >
{
    typedef
        proto::extends< Expr, MyDoubleExpr< Expr >, proto::default_domain >
    base_type;

    MyDoubleExpr( Expr const &expr = Expr() )
      : base_type( expr )
    {}

  // Overloading of all Constructors supported by the custom type
  typedef typename proto::terminal< my_type >::type expr_type;
  MyDoubleExpr( double const &d)
    : base_type( expr_type::make(my_type(d)))
    {}

  // Lazy assignment is desired
    BOOST_PROTO_EXTENDS_USING_ASSIGN(MyDoubleExpr)

};

// unintrusively replace the existing type with
// the expression template
typedef MyDoubleExpr<> replaced_type;


int main() {

  replaced_type a = 2.0, b = 1.5;

  proto::default_context ctx;

  // The replaced type is created as template specialisation
  // proto::terminal< my_type >::type -> cannot store expressions
  replaced_type c;
  c = (a + b) * 2.0;
  std::cout << "c: " << proto::eval(c,ctx) << endl << endl;
  proto::display_expr(c);

  // Initialisation does not work directly ?
  //replaced_type d = a+b;

  // using auto works fine, so the expression basically works
  auto e = (a + b) * 2.0;
  std::cout << "e: " << proto::eval(e,ctx) << endl;
  proto::display_expr(e);

  getchar();
  return 0;
}

私たちの主な問題は、リテラルと式の両方で同様に機能する型を定義できないことです。この例では、c は proto::terminal 型の Expression であり、式の代入を無視します。auto を使用して式を保存すると、正常に機能します。また、直接初期化することはできません。

問題を正しく理解していれば、式とリテラルに 2 つの異なる型が必要になりますが、既存の型しか変更できないため、これは不可能です。

また、BOOST_PROTO_DEFINE_OPERATORS(...) を使用してカスタム型を非侵入型端末にするなど、他のオプションも調べましたが、遅延代入も不可能です。

それで、私たちの質問は、私たちが望むものを達成できるかどうか、または遅延評価を導入するために既存のコードを変更する必要があるかどうかです.

助けてくれてありがとう、マティアスenter code here

4

1 に答える 1

1

Proto のドキュメントの遅延ベクトルの例を見てください。lazy_vector_expr遅延ベクトル式のテンプレートと、端末lazy_vector専用のテンプレート (実装のほとんどを から継承lazy_vector_expr) があります。任意の遅延ベクトル式を受け入れて評価し、結果を格納lazy_vectorする演算子を定義します。+=

似たようなことをしているような気がします。しかし、代わりに+=、通常の割り当てと変換構造を探しています。したがって、テンプレート化されたコンストラクターと代入演算子を定義します。(未テスト)のようなもの...

template<typename XXX = proto::is_proto_expr> // hack, needed to for ADL
struct replaced_type_t
  : MyDoubleExpr< proto::terminal<double>::type > 
{
    replaced_type_t(double d = 0.0)
      : MyDoubleExpr< proto::terminal<double>::type >(
            proto::terminal<double>::type::make(d)
        )
    {}
    // Converting constructor
    template<typename OtherExpr>
    replaced_type_t(MyDoubleExpr<OtherExpr> const & e)
    {
        // Evaluate e, assign to *this
    }
    // Converting assignment
    template<typename OtherExpr>
    replaced_type_t& operator=(MyDoubleExpr<OtherExpr> const & e)
    {
        // Evaluate e, assign to *this
    }
};

typedef replaced_type_t<> replaced_type;

ちなみに、 を使用するBOOST_PROTO_EXTENDS_USING_ASSIGNと、より大きな式を構築するオーバーロードされた代入演算子が得られました。したがって、この:

replaced_type c;
c = (a + b) * 2.0;

MyDoubleExpr<>...代入ノードを含むテンポラリを作成し、それを破棄するという興味深い効果があります。

チッ!

于 2013-04-26T01:26:12.523 に答える