自定义类型的运算符优先级,以及当存在多个相同运算符时是否可能进行延迟求值

Operator precedence for custom types and is it possible to have lazy evaluation when multiples of the same operator are present?

本文关键字:运算符 是否 延迟 优先级 类型 存在 自定义      更新时间:2023-10-16

假设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的运算符。所以这个数组被遍历两次。是否有可能有延迟评估执行全局操作时,同一操作符的倍数和/或多个操作符的倍数存在?

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

这是因为你的"array - float"操作符没有将数组作为const引用。因此,为2.0 - marray创建的临时不能绑定到它。在链接到最小的工作示例中,您使用2 - marray - 5,当编译器生成要减去5的代码时,它将使用接受整数的构造函数构造一个新数组,然后在两个数组成员之间调用减法运算符。

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