我試圖將懶惰評估引入到現有的代碼項目中。項目核心基本上包含大量使用自定義類型的計算(它的行爲類似於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類型的表達式,並且忽略表達式的賦值。使用自動存儲表達式時,它工作正常。而且,直接初始化是不可能的。
如果我正確理解我們的問題,我們需要兩種不同類型的表達式和文字,這是不可能的,因爲我們只能改變現有的類型。
我們還研究了其他選項,例如使用BOOST_PROTO_DEFINE_OPERATORS(...)使我們的自定義類型成爲非侵入性終端,但懶惰賦值也是不可能的。
所以,我們的問題是如果我們能夠實現我們想要的或者我們必須改變現有的代碼來引入懶惰評估?
感謝您的幫助, 馬蒂亞斯enter code here
謝謝。得到它與輕微的變化(我不得不直接使用OtherExpr而不是MyDoubleExpr作爲賦值參數)。評估和計算工作正常。唯一的問題是這會急於計算每一個表達式。爲了獲得更好的優化選項,如果賦值不評估表達式,而是懶惰地存儲它,那將會很好。 –
MatthiasB
2013-04-26 16:37:27
不確定你的意思是「懶惰地存儲」。你想什麼時候評估它? – 2013-04-26 18:43:19
最好的情況下,只有當我在程序結束時調用proto :: eval(c,ctx)時。在此之前,任何表達式只能存儲。我們理想的用例是我們可以在整個程序(包含一組輸入參數和一個結果值)上構建一個表達式樹,跨越幾個計算和函數調用。 – MatthiasB 2013-04-26 20:20:46