【问题标题】:What is the difference between equality-preserving and stable?保持平等和稳定有什么区别?
【发布时间】:2019-09-26 05:11:34
【问题描述】:

根据draft

如果给定相等的输入,表达式会产生相等的输出,则表达式是保持平等的。[...]

[...]稳定:对于具有相同输入对象的此类表达式的两次评估需要具有相等的输出,而无需对这些输入对象进行任何显式干预修改。[...]

强调我的。

  • 这些有什么区别?

  • 什么时候表达式可以保持平等但不是稳定反之亦然

【问题讨论】:

  • “稳定”的输入对象不必相等。

标签: c++ language-lawyer c++-concepts


【解决方案1】:

对于修改其输入的操作,两者会有所不同。

// stable and equality preserving
int foo(int a, int b) { 
    return a + b;
}

// equality preserving, but not stable:
int bar(int a, int &b) { 
    auto ret = a + b;
    ++b;
    return ret;
}

例如:

int x = 1, y = 2;
int z = foo(x, y); // produces 3

int z2 = foo(x, y);  // still produces 3

int zz = bar(x, y); // produces 3
int zz2 = bar(x, y); // produces 4

至于稳定但不保持平等的东西,是的,这也是可能的(对于“平等”的某些定义)。

举个简单的例子,考虑这样的事情:

struct foo { 
    int bar;

    // they're all equal, just some are more equal than others
    bool operator==(foo const &) const { return true; }
};

int operator+(foo a, foo b) { return a.bar + b.bar; }

foo a{1};
foo b{2};
foo c{3};

// obviously both true
assert(a == b);
assert(b == c);

int x = a + b;
int y = b + c;

assert(x != y); // of course 1 + 2 != 2 + 3;

【讨论】:

  • 太棒了!这澄清了“equality-preserving 但不是stable”的情况。是否可能出现相反的情况?
  • @Nazinho 不,不是。只要它是稳定的,它也是保持平等的。
  • @Jerry Coffin 我希望将来该标准能够明确他们所指的“相等”的定义。无论如何,这个文本是不规范的。
  • @Nazinho 对象的价值是纯粹的主观属性。您可以通过多种方式定义String 对象的“值”。
【解决方案2】:

批准的答案不正确。 这个函数:

int foo(int a, int b) { 
    return a + b;
}

确实是保持平等和稳定的。 但是这个函数也是如此:

int bar(int a, int &b) { 
    auto ret = a + b;
    ++b;
    return ret;
}

两者的实际区别在于 foo 是正则的(参见概念 regular_invocable),而 bar 不是。

一个保持相等但不稳定的函数的例子是:

int b = 0;  // assume accessible by other threads
int zip(int a) { 
    auto ret = a + b;
    ++b;
    return ret;
}

它是保持等式的,因为等式保持纯粹是静态,并且在任何给定时间,zip 确实会在相同的输入下给出相同的结果。

然而,zip 并不稳定,因为稳定性是动态的,并且在不同的时间,zip可能在相同的输入下给出不同的结果。

(如果全局变量b在调用之间没有改变,那么它会给出不同的结果。但是如果另一个线程减少b,并且没有发生其他变化,它会给出相同的结果。)

(如果没有其他线程可以访问 b 变量,尽管这实际上是如何实现的,我们将具有稳定性,因为我们可以观察到“显式干预修改”。这就是标准提到稳定性禁止“自发”的原因变化,也就是波动性,来自其他执行线程的变化等等。参见concepts.lib.general.equality)

还请注意,相等性保留不依赖于相等运算符的可用性(并且equal_comparable 概念实际上需要相等性保留)。平等没有明确定义,但应该被认为是可替代性或不可区分性,这在标准中经常提到,例如在strong_ordering中。

如果不保持相等,函数就不可能是稳定的,因为稳定性是静态的相等保持概念的动态扩展。

【讨论】:

  • 来自标准:'需要保持相等性的表达式还需要稳定:具有相同输入对象的此类表达式的两次评估需要具有相同的输出,而没有任何显式干预修改那些输入对象。'显然bar 的两个评估不会有相同的输出,所以我不同意你的解释。
猜你喜欢
  • 2015-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 2020-10-20
  • 1970-01-01
  • 2017-01-29
相关资源
最近更新 更多