C++凤凰城中的 boost::lambda::ret 等效项

发布于 2024-09-01 19:49:16 字数 113 浏览 2 评论 0原文

Boost lambda 允许使用 ret模板覆盖推导的返回类型。 我尝试在 Phoenix 中搜索等效项,但找不到。

凤凰有类似的吗?我知道如何制作自己的替代品,但我不愿意。谢谢

Boost lambda allows to overwrite deduced return type using ret<T> template.
I have tried searching for equivalent in phoenix but could not find one.

Is there an equivalent in phoenix? I know how to make my own Replacement but I would rather not. thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

白首有我共你 2024-09-08 19:49:16

重写:我错过了第一个答案的要点(已经晚了),让我再试一次。

让我为像我这样第一次可能会错过你的观点的人做一些解释。在 boost::lambda 中,当在运算符表达式中使用用户定义类型时,必须使用 ret<> 。覆盖返回类型推导的函数。这是因为 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

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

using namespace boost::phoenix;

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

返回类型推导系统在 phoenix 中完全不同,并且更加自然;它将正确推断出使用常规语义的运算符的返回类型。具体来说,返回类型应与操作数之一的类型匹配,是指向参数类型之一的引用、指针或 const 指针,或者是这些类型之一的 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;
};

对于 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_operation 模板结构(第 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 的替代品,但在某种意义上它更好,因为它全球的。如果有很多运算符需要重载,则可以对整套操作进行宏定义。

Rewrite: I missed the point on my first answer (it was late), let me try again.

Let me give some exposition for people like me who might miss your point the first time. In boost::lambda, when using user defined types in operator expressions, one has to use the ret<> function to override return type deduction. This is because the lambda return type deduction system only supports native (and stl? I don't remember) types directly. A short example:

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

In phoenix though, no hints are are needed (note that literals and non-const temporaries cannot appear in a phoenix argument list):

using namespace boost::phoenix;

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

The return type deduction system is completely different and much more natural in phoenix; it will properly deduce the return type of operators that use conventional semantics. Specifically, the return type should match the type of one of the operands, be a reference, pointer, or const pointer to one of the argument types, or be an stl container/container iterator of one of those types. There is a nice write up of phoenix return type deduction in type_deduction.hpp header for more details.

So now I'm reading your question as, how can non-conventional operator semantics be handled in phoenix?

Consider the following strange pair of types as an example

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

For lambda, this is no problem, just use the ret function:

using namespace boost::lambda;

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

But phoenix can't deal with this operator (can you blame it?) because the return type is not related to the arguments, and there is no way to directly indicate the return type in phoenix. If there is a good reason to use an operator like this, a case could be added to the type deduction system, but I can't see a way to do this without hacking type_deduction.hpp or branching a good portion of phoenix.

Alternatively, I figured out a little hack to override the return types for specific operators. The result_of_operation template structures in boost/spirit/home/phoenix/operator/arithmetic.hpp (lines 39-56 list the struct types, boost 1.43) execute the type deduction when they are instantiated and store the result. So all that is needed is to provide some template specializations for the problem operations, which only need contain one typedef specifying the return type. Example (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;
}

This certainly isn't a ret replacement, but in some senses its better since its global. If there are a lot of operators to overload, the full set of operations could be macroed.

孤千羽 2024-09-08 19:49:16

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

AFAIK, this (or something similar) is not supported in Phoenix. If you described your use case I might be able to help, though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文