3

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

凤凰有等价物吗?我知道如何制作自己的替代品,但我宁愿不这样做。谢谢你

4

2 回答 2

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

但是在 phoenix 中,不需要任何提示(请注意,文字和非常量临时变量不能出现在 phoenix 参数列表中):

using namespace boost::phoenix;

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

回扣式的扣法系统在凤凰城中完全不同,自然得多;它将正确推断使用常规语义的运算符的返回类型。具体来说,返回类型应该与其中一个操作数的类型匹配,可以是指向其中一种参数类型的引用、指针或 const 指针,或者是其中一种类型的 stl 容器/容器迭代器。type_deduction.hpp 标头中有一个很好的关于 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;
};

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

using namespace boost::lambda;

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

但是phoenix处理不了这个操作符(能怪它吗?),因为返回类型与参数无关,也没有办法在phoenix中直接指明返回类型。如果有充分的理由使用这样的运算符,则可以将案例添加到类型推导系统中,但如果不破解 type_deduction.hpp 或分支 phoenix 的大部分内容,我看不到这样做的方法。

或者,我想出了一个小技巧来覆盖特定运算符的返回类型。boost/spirit/home/phoenix/operator/arithmetic.hpp 中的 result_of_操作模板结构(第 39-56 行列出了结构类型,boost 1.43)在实例化时执行类型推导并存储结果。所以只需要为问题操作提供一些模板特化,只需要包含一个 typedef 指定返回类型。示例(完整 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 替代品,但从某种意义上说,它是全球性的。如果有很多运算符要重载,则可以宏化整个操作集。

于 2010-05-26T07:14:47.523 回答
0

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

于 2010-05-24T23:56:21.493 回答