【问题标题】:Operator precedence for custom types and is it possible to have lazy evaluation when multiples of the same operator are present?自定义类型的运算符优先级,当存在多个相同运算符时是否可以进行惰性求值?
【发布时间】:2015-12-16 06:33:45
【问题描述】:

假设array 是一个自定义类型,定义为本质上管理资源的类

class array {
public:
    size_t size;
    float *data;
};

为了使operator -array 执行元素级标量加法并能够处理array+floatfloat+array 的左右关联,我们像这样重载它

array operator -(float lhs, const array& rhs)
{
    array tmp(rhs.size);
    for (size_t i=0;i<rhs.size;++i)
        tmp.data[i] = lhs-rhs.data[i];

    return tmp;
}

array operator -(array& lhs, float rhs)
{
    array tmp(lhs.size);
    for (size_t i=0;i<lhs.size;++i)
        tmp.data[i] = lhs.data[i]-rhs;
    return tmp;
}

假设我们也有一个initializer_list 构造函数,所以我们可以这样做

array marray = {1.0f,2.0f,3.0f,4.0f};

现在

std::cout << marray-5.0 << "\n"; 
std::cout << 2.0-marray << "\n";

我们得到了想要的结果,但是这样做

std::cout << 2.0-marray-5.0 << "\n";

甚至没有为marray-5.0 调用第二个重载,并为输出数组的最后两个元素提供了无意义的值,当然2.0-(marray-5.0) 确实解决了问题,但不是通用解决方案。所以问题是:

  1. 到底发生了什么?为什么根本不调用第二个重载?这是否与运算符优先级有关?
  2. 我的第二个问题是关于第二种情况的,即2.0-(marray-5.0),这里我们调用一次float+array 的运算符和一次array+float 的运算符。所以数组被遍历了两次。当存在多个相同运算符和/或多个运算符的倍数时,是否可以进行惰性评估以一次执行全局操作?

编辑: Here 是一个最小的工作示例。注意第二个重载中的missing const,我用另一个array operator -(const array&amp; other) 重载来消除歧义,用于两个数组的元素减法。我想这是第一个问题的原因。

【问题讨论】:

  • 您需要提供一个小而完整的代码示例来展示您的问题。正如尝试流式传输array(无流式操作符)的代码所展示的那样,您没有证据表明构造函数可以进行大小调整等。任何缺少的东西都可能是贡献者,这让任何人都想提供帮助您处于试图猜测缺少什么的位置。是的,可以进行惰性求值,但这依赖于多个函数(成员、构造函数等)协同工作。
  • 我已将链接添加到产生结果的小型工作示例。
  • 顺便说一句,尽快切换到std::vector&lt;float&gt;std::unique_ptr&lt;float[]&gt;。没有理由手动编写析构函数,并且后一种选项的开销为零。
  • 而您正在寻找实现惰性评估的是“表达式模板”模式。它在 C++ 矩阵库中非常流行。

标签: c++ arrays lazy-evaluation operator-precedence associativity


【解决方案1】:

发生这种情况是因为您的“数组 - 浮点”运算符没有将数组作为 const 引用。因此,为2.0 - marray 创建的临时文件无法绑定到它。在链接到最小工作示例中,您使用 2 - marray - 5,当编译器生成减 5 的代码时,它将使用采用整数的构造函数构造一个新数组,然后在两个数组成员之间调用减法运算符。

将您的第二个减法运算符更改为array operator -(const array&amp; lhs, float rhs)

【讨论】:

  • 在单参数构造函数上使用explicit 也是一个好主意,这样就不会发生这种意外的转换。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-25
  • 1970-01-01
  • 1970-01-01
  • 2011-07-07
相关资源
最近更新 更多