C++ 中是否可以重载运算符结合性?

2024-01-08

我正在构建一个具有稍微不对称添加的类。在投诉到来之前,它必然是不对称的。当两个对象相加时,必须发生转换(需要一些时间的操作),并且转换最自然地发生在正确的被加数上。

为了具体说明这一点,这里有一个正在发生的事情的通用示例......

class Foo {
    char _fav;
    int _prop;

public:
    const char fav() const {return _fav;}
    const int prop() const (return _prop;}
    void changeFav(char); // complicated method that also changes _prop
    void changeProp(int); // straightforward method
}

Foo
operator + (Foo A, Foo B) {
    Foo sum;
    if (A.fav() != B.fav()) A.changeFav(B.fav);
    sum.changeProp(A.prop() + B.prop());   
    return sum;
}

为了两个Foo要添加,它们需要具有相同的_fav,因此必须选择要转换的内容。根据以下详细信息Foo,最自然的做法是更改左被加数以匹配右被加数。

然而,当做:

Foo A,B,C;
Foo D = A + B + C; // D = (A + B) + C
Foo E = A + (B + C);

if A已经有相同的了_fav as C, then changeFav被调用两次D(一旦改变A._fav to B._fav然后再次改变(A+B)._fav to C._fav)和一次E(改变B._fav to C._fav)。我更喜欢后者,但希望避免强迫用户使用括号进行多次添加。

有没有办法超载关联性operator +让这一切发生?


你可以进行黑客攻击。您必须使用另一种类型来保存操作的中间结果,然后您可以使用隐式强制转换来评估结果。下面是如何在 C++ 中实现 Python 风格的比较运算符的示例:

#include <vector>
#include <cstdio>

struct S {
    S(int x) : val(x) { }
    int val;
};

struct Comparison {
    std::vector<S> operands;
    explicit Comparison(S x)
    {
        operands.push_back(x);
    }
    operator S()
    {
        auto i = operands.begin(), e = operands.end();
        S prev = *i;
        for (i++; i != e; i++) {
            S cur = *i;
            if (prev.val >= cur.val)
                return S(0);
            prev = cur;
        }
        return S(1);
    }
    void append(const Comparison &a)
    {
        operands.insert(
            operands.end(),
            a.operands.begin(),
            a.operands.end());
    }
    void append(const S &a)
    {
        operands.push_back(a);
    }
};

Comparison operator<(const Comparison &left, const Comparison &right)
{ Comparison result(left); result.append(right); return result; }
Comparison operator<(const Comparison &left, const S &right)
{ Comparison result(left); result.append(right); return result; }
Comparison operator<(const S &left, const Comparison &right)
{ Comparison result(left); result.append(right); return result; }
Comparison operator<(const S &left, const S &right)
{ Comparison result(left); result.append(right); return result; }

int main()
{
    S x(0);
    x = S(0) < S(1) < S(2) < S(3);
    std::printf("0 < 1 < 2 < 3 = %d\n", x.val);
    x = S(0) < S(1) < S(3) < S(2);
    std::printf("0 < 1 < 3 < 2 = %d\n", x.val);
    return 0;
}

然而,在这种情况下,我会很快放弃+操作员。我会避免使用+对于任何不结合和交换的运算,因为这是约定+在数学中。相反,您可以使用可变参数函数(使用模板)来执行所需的计算。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 中是否可以重载运算符结合性? 的相关文章

  • 用于代数简化和求解的 C# 库 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 网络上有很多代数求解器和简化器 例如 algebra com 上不错的代数求解器和简化器 然而 我正在
  • 为什么 int8_t 和用户通过 cin 输入显示奇怪的结果[重复]

    这个问题在这里已经有答案了 一小段代码让我发疯 但希望你能阻止我跳出窗外 看这里 include
  • 如何将 protobuf-net 与不可变值类型一起使用?

    假设我有一个像这样的不可变值类型 Serializable DataContract public struct MyValueType ISerializable private readonly int x private readon
  • 在 DataView 的 RowFilter 中选择 DISTINCT

    我试图根据与另一个表的关系缩小 DataView 中的行范围 我使用的 RowFilter 如下 dv new DataView myDS myTable id IN SELECT DISTINCT parentID FROM myOthe
  • 复制 std::function 的成本有多高?

    While std function是可移动的 但在某些情况下不可能或不方便 复制它会受到重大处罚吗 它是否可能取决于捕获变量的大小 如果它是使用 lambda 表达式创建的 它依赖于实现吗 std function通常被实现为值语义 小缓
  • C中的malloc内存分配方案

    我在 C 中尝试使用 malloc 发现 malloc 在分配了一些内存后浪费了一些空间 下面是我用来测试 malloc 的一段代码 include
  • 将 Word 文档另存为图像

    我正在使用下面的代码将 Word 文档转换为图像文件 但是图片显得太大 内容不适合 有没有办法渲染图片或将图片保存到合适的尺寸 private void btnConvert Click object sender EventArgs e
  • 在 C 中初始化变量

    我知道有时如果你不初始化int 如果打印整数 您将得到一个随机数 但将所有内容初始化为零似乎有点愚蠢 我问这个问题是因为我正在评论我的 C 项目 而且我对缩进非常直接 并且它可以完全编译 90 90 谢谢 Stackoverflow 但我想
  • 为什么调用非 const 成员函数而不是 const 成员函数?

    为了我的目的 我尝试包装一些类似于 Qt 共享数据指针的东西 经过测试 我发现当应该调用 const 函数时 会选择它的非 const 版本 我正在使用 C 0x 选项进行编译 这是一个最小的代码 struct Data int x con
  • 是否有实用的理由使用“if (0 == p)”而不是“if (!p)”?

    我倾向于使用逻辑非运算符来编写 if 语句 if p some code 我周围的一些人倾向于使用显式比较 因此代码如下所示 if FOO p some code 其中 FOO 是其中之一false FALSE 0 0 0 NULL etc
  • 从 Linux 内核模块中调用用户空间函数

    我正在编写一个简单的 Linux 字符设备驱动程序 以通过 I O 端口将数据输出到硬件 我有一个执行浮点运算的函数来计算硬件的正确输出 不幸的是 这意味着我需要将此函数保留在用户空间中 因为 Linux 内核不能很好地处理浮点运算 这是设
  • 我可以使用 moq Mock 来模拟类而不是接口吗?

    正在经历https github com Moq moq4 wiki Quickstart https github com Moq moq4 wiki Quickstart 我看到它 Mock 一个接口 我的遗留代码中有一个没有接口的类
  • 如何禁用 fread() 中的缓冲?

    我正在使用 fread 和 fwrite 读取和写入套接字 我相信这些函数用于缓冲输入和输出 有什么方法可以在仍然使用这些功能的同时禁用缓冲吗 Edit 我正在构建一个远程桌面应用程序 远程客户端似乎 落后于服务器 我不知道可能是什么原因
  • AES 128 CBC 蒙特卡罗测试

    我正在 AES 128 CBC 上执行 MCT 如中所述http csrc nist gov groups STM cavp documents aes AESAVS pdf http csrc nist gov groups STM ca
  • 如何设置 log4net 每天将我的文件记录到不同的文件夹中?

    我想将每天的所有日志保存在名为 YYYYMMdd 的文件夹中 log4net 应该根据系统日期时间处理创建新文件夹 我如何设置它 我想将一天中的所有日志保存到 n 个 1MB 的文件中 我不想重写旧文件 但想真正拥有一天中的所有日志 我该如
  • 调用堆栈中的“外部代码”是什么意思?

    我在 Visual Studio 中调用一个方法 并尝试通过检查调用堆栈来调试它 其中一些行标记为 外部代码 这到底是什么意思 方法来自 dll已被处决 外部代码 意味着该dll没有可用的调试信息 你能做的就是在Call Stack窗口中单
  • 如果没有抽象成员,基类是否应该标记为抽象?

    如果一个类没有抽象成员 可以将其标记为抽象吗 即使没有实际理由直接实例化它 除了单元测试 是的 将不应该实例化的基类显式标记为抽象是合理且有益的 即使在没有抽象方法的情况下也是如此 它强制执行通用准则来使非叶类抽象 它阻止其他程序员创建该类
  • WebSocket安全连接自签名证书

    目标是一个与用户电脑上安装的 C 应用程序交换信息的 Web 应用程序 客户端应用程序是 websocket 服务器 浏览器是 websocket 客户端 最后 用户浏览器中的 websocket 客户端通过 Angular 持久创建 并且
  • 我的班级应该订阅自己的公共活动吗?

    我正在使用 C 3 0 遵循标准事件模式我有 public event EventHandler
  • 使用 .NET Process.Start 运行时挂起进程 - 出了什么问题?

    我在 svn exe 周围编写了一个快速而肮脏的包装器来检索一些内容并对其执行某些操作 但对于某些输入 它偶尔会重复挂起并且无法完成 例如 一个调用是 svn list svn list http myserver 84 svn Docum

随机推荐