使结构体的所有数学运算符操作同一成员

Making all mathematical operators of a struct manipulate the same member

本文关键字:操作 运算符 成员 结构体      更新时间:2023-10-16

我有一个结构体包含一个双精度体和几个标志,但是我想在我的代码中使用它,就好像它只是那个双精度体一样。是否有一种方法可以简化以下代码,以便在此结构体的实例上执行的所有数学运算符都在包含双精度对象上执行?我的代码运行,但我怀疑c++有一个非常优雅和简短的解决方案来解决我的问题。

struct SomeStruct
{
    double value;
    bool someFlag;
    bool someOtherFlag;
    operator double(){return value;}
    void operator=(double newValue){value = newValue;}
    void operator+=(double valueToAdd){value += valueToAdd;}
    void operator-=(double valueToSubtract){value-= valueToSubtract;}
    void operator/=(double divisor){value /= divisor;}
    void operator*=(double multiplier){value *= multiplier;}
    double operator+(double valueToAdd){return value + valueToAdd;}
    ...
}

如果您将转换操作符更改为operator double &,则可以免费获得double上的所有操作符,除了operator=:

#include <iostream>
struct Foo {
    double d;
    bool flag;
    Foo() : d(0), flag(false) {}
    operator double &() { return d; }
};
int main()
{
    Foo x;  // initialized to (0, false)
    x.flag = true;
    x += 1.1;
    std::cout << x.d << " " << x.flag << std::endl;
    x *= 2;
    std::cout << x.d << " " << x.flag << std::endl;
}

打印

1.1 1
2.2 1

(第二个输出是flag)。

也可以定义operator double() const

把我们在评论中的讨论变成一个答案…

我认为你根本不应该做这件事。正如您在评论中提到的,您的结构体包含来自声学测量的信息,因此它既有值也有标志,表明噪声测量是否使记录仪器过载。让我把你的结构简化成这样:

struct Noise
{
  double noiseLevel;
  bool overload;
};

现在让我们假设您添加了一个转换操作符,从而获得了转换操作符提供的轻松和方便。现在你有两个噪声测量quietloudloud有过载标志设置,而quiet没有。现在您可以执行以下两个操作,读者应该期望它们产生相同的结果:

loud += quiet;

quiet += loud;

,但是因为你的加法不尊重标志,两个操作产生不同的值。在第一个中,设置了overload标志,而在第二个中没有设置。在我看来,这是非常令人不安的行为。因此,我建议您实现自己的、尊重类型的、以自然方式保留overlaud标志的操作符,例如

Noise& operator+=(Noise& lhs, const Noise& rhs)
{
  lhs.value += rhs.value;
  lhs.overload |= rhs.overload;
  return lhs;
}