Boost lambda 允许使用ret<T>
模板覆盖推导的返回类型。我曾尝试在 phoenix 中搜索等价物,但找不到。
凤凰有等价物吗?我知道如何制作自己的替代品,但我宁愿不这样做。谢谢你
Boost lambda 允许使用ret<T>
模板覆盖推导的返回类型。我曾尝试在 phoenix 中搜索等价物,但找不到。
凤凰有等价物吗?我知道如何制作自己的替代品,但我宁愿不这样做。谢谢你
重写:我在第一个答案上错过了重点(已经很晚了),让我再试一次。
让我为像我这样可能第一次错过你的观点的人做一些说明。在 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 替代品,但从某种意义上说,它是全球性的。如果有很多运算符要重载,则可以宏化整个操作集。
AFAIK,凤凰城不支持这个(或类似的东西)。不过,如果您描述了您的用例,我可能会提供帮助。