2010-05-19 54 views
3

Boost lambda允許使用ret<T>模板覆蓋推導的返回類型。 我曾嘗試在鳳凰中搜索等價物,但找不到一個。Phoenix中的C++ boost :: lambda :: ret等效

菲尼克斯有沒有等價物?我知道如何讓自己的替代品,但我寧願不。謝謝

回答

8

重寫:我錯過了第一個答案的時間點(已經晚了),讓我再試一次。

讓我來對像我這樣第一次可能會錯過你的觀點的人給予一些解釋。在boost :: lambda中,當在運算符表達式中使用用戶定義的類型時,必須使用ret函數來覆蓋返回類型推導。這是因爲lambda返回類型推導系統僅直接支持native(和stl?我不記得)類型。一個簡單的例子:

using namespace boost::lambda; 

struct add_t{ 
    add_t(int i) : i(i) {}; 
    add_t operator+(const add_t& other) const{ 
     return add_t(i + other.i); 
    } 
    int i; 
}; 

(_1 + _2)(add_t(38), add_t(4));   // RETURN TYPE DEDUCTION FAILS 
ret<add_t>(_1 + _2)(add_t(38), add_t(4)); // OK 

在鳳凰城雖然是不需要提示(注意,文本和非const臨時對象不能出現在鳳凰參數列表):

using namespace boost::phoenix; 

add_t i(38), j(4); 
(_1 + _2)(i, j); // JUST FINE 

返回類型推演系統在鳳凰中完全不同並且更自然;它會正確地推導出使用傳統語義的操作符的返回類型。具體而言,返回類型應該匹配其中一個操作數的類型,可以是參數,指針或指向其中一個參數類型的指針,或者是其中一種類型的stl容器/容器迭代器。有關鳳凰返回類型扣除type_deduction.hpp header有一個很好的寫法更多的細節。

所以,現在我正在閱讀你的問題,如何在phoenix中處理非常規的操作符語義?

考慮以下怪對類型作爲一個例子

struct add_ret_t{ 
    add_ret_t(int i) : i(i) {}; 
    int i; 
}; 

struct add_t{ 
    add_t(int i) : i(i) {}; 
    add_ret_t operator+(const add_t& other) const{ 
     return add_ret_t(i + other.i); 
    } 
    int i; 
}; 

對於拉姆達,這是沒有問題的,只要使用RET功能:

using namespace boost::lambda; 

ret<add_ret_t>(_1 + _2)(add_t(38), add_t(4)); // OK 

但鳳凰無法處理這運算符(你能責怪它嗎?),因爲返回類型與參數無關,並且沒有辦法直接指出phoenix中的返回類型。如果有充分的理由使用這樣的操作符,可以在類型扣除系統中添加一個案例,但是我不能在沒有黑客入侵type_deduction.hpp或分支很多phoenix的情況下找到這種方法。

另外,我想出了一些小技巧來覆蓋特定操作符的返回類型。 boost/spirit/home/phoenix/operator/arithmetic.hpp中的模板結構(第39-56行列出結構類型,boost 1.43)在實例化並存儲結果時執行類型扣減。所以所需要的只是爲問題操作提供一些模板專門化,它們只需要包含一個指定返回類型的typedef。示例(codepad for full src):

using namespace boost::phoenix; 

namespace boost{ namespace phoenix{ 

//override add_t addition to give add_ret_t 
template <> struct result_of_plus<add_t&, add_t&> { typedef add_ret_t type; }; 

//override int addition to give char 
template <> struct result_of_plus<int&, int&> { typedef char type; }; 

}} 

int main() 
{ 
    add_t i = 1, j = 7; 
    std::cout << ((_1 + _2)(i, j)).i << std::endl; 

    int k = 51, l = 37; 
    std::cout << ((_1 + _2)(k, l)) << std::endl; 

    return 0; 
} 

這當然不是一個RET替代品,但在某種意義上它,因爲它的全球性更好。如果有很多操作員超載,那麼可以宏觀操作整套操作。

0

AFAIK,這(或類似的)在鳳凰城不支持。不過,如果您描述了我的使用案例,我可能會提供幫助。