C ++ boost :: lambda :: ret等效于凤凰

时间:2010-05-19 17:16:17

标签: c++ boost-spirit boost-lambda boost-phoenix

Boost lambda允许使用ret<T>模板覆盖推断的返回类型。 我曾尝试在凤凰中搜索等效物,但找不到它。

凤凰有没有相同的东西?我知道怎么做自己的替换,但我宁愿不做。谢谢

2 个答案:

答案 0 :(得分:8)

重写:我错过了第一个回答的问题(已经很晚了),让我再试一次。

让我为像我这样第一次可能会错过你的观点的人做一些阐述。在boost :: lambda中,当在运算符表达式中使用用户定义的类型时,必须使用ret&lt;&gt;函数覆盖返回类型推导。这是因为lambda返回类型推导系统仅直接支持本机(和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

在凤凰中,不需要任何提示(请注意,文字和非常设临时数不能出现在凤凰参数列表中):

using namespace boost::phoenix;

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

返回式演绎系统完全不同,在凤凰中更自然;它将适当地推导出使用传统语义的运算符的返回类型。具体来说,返回类型应该与其中一个操作数的类型匹配,是一个参数类型的引用,指针或const指针,或者是其中一个类型的stl容器/容器迭代器。有关详细信息,请在type_deduction.hpp header中详细介绍凤凰返回类型演绎。

所以现在我正在读你的问题,如何在凤凰中处理非传统的算子语义?

考虑以下奇怪的一对类型作为示例

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;
};

对于lambda,这没问题,只需使用ret函数:

using namespace boost::lambda;

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

但是凤凰无法处理这个运算符(你可以怪它吗?)因为返回类型与参数无关,并且没有办法直接指示凤凰的返回类型。如果有充分的理由使用这样的运算符,可以在类型推导系统中添加一个案例,但是我没有办法在没有黑客攻击type_deduction.hpp或分支很好的凤凰部分的情况下这样做。

或者,我想出了一个小的黑客来覆盖特定运算符的返回类型。 boost / spirit / home / phoenix / operator / arithmetic.hpp中的result_of_ 操作模板结构(第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;
}

这肯定不是替代品,但从某种意义上来说,它的全球化程度更高。如果有很多运算符需要重载,则可以对整个操作集进行宏操作。

答案 1 :(得分:0)

AFAIK,凤凰城不支持此(或类似的东西)。如果您描述了您的用例,我可能会提供帮助。