c++ 我如何重写这个Assert,使它一次通过,以后失败?

slwdgvem  于 2023-02-06  发布在  其他
关注(0)|答案(1)|浏览(118)

作为一个练习,我想检查一下,在一个assert中,我以前是否看到过某个(布尔)状态。看到它从来没有是可以的,看到它一次是可以的,但是看到它两次应该会引发一个Assert。(确切地说,在看到它一次之后看到 anything 应该会引发一个Assert。)
我尝试过assert(!(seen & (seen |= is_here)));--然而,它在不同编译器中的表现非常不一致。

#include <iostream>
#include <assert.h>

int main() {
    bool seen = false;
    bool is_here;

    is_here = false;
    // these shall pass
    assert(!(seen & (seen |= is_here)));
    assert(!(seen & (seen |= is_here)));

    is_here = true;
    // this shall pass, but fails in MSVC
    assert(!(seen & (seen |= is_here)));
    // after that, this shall pass
    assert( (seen & (seen |= is_here)));

    is_here = false;
    // same as this
    assert( (seen & (seen |= is_here)));

    std::cout << "Done.";

    return 0;
}

我想我碰到了一堵未定义行为的墙,所以我试着重写我的表达式,但没有成功。(我想这可能是一个逻辑问题,而不是编程问题。)我试着用&&||重写,它们有序列点,但由于它们也是短路的,我还没有找到正确的表达式。

xdyibdwo

xdyibdwo1#

通过反复试验,我已经能够得出assert(seen ? false : true | (seen |= is_here)),关键是?引入了一个序列点,将seen的两个求值分开,此外,true | ...设置后一个分支的值,而不会短路。

#include <iostream>
#include <assert.h>

int main() {
    bool seen = false;
    bool is_here;

    is_here = false;
    // pass
    assert(seen ? false : true | (seen |= is_here));
    assert(seen ? false : true | (seen |= is_here));

    is_here = true;
    // passes
    assert(seen ? false : true | (seen |= is_here));
    // after that, this passes
    assert(!(seen ? false : true | (seen |= is_here)));

    is_here = false;
    // same as this
    assert(!(seen ? false : true | (seen |= is_here)));

    std::cout << "Done.";

    return 0;
}

相关问题