对象的状态在其构造之后和成员函数调用之前发生变化

问题描述 投票:0回答:1

下面的程序已尽可能减少以显示 Visual Studio C++ 编译器遇到的问题。

f
是一些接受输入谓词对象
P p
的算法函数,它具有用户定义的复制构造函数,可以记住源对象上的指针。在该构造函数中,检查源对象和复制对象确实不同
if (s == this) throw 0;
但在
operator ()
中,相同的检查返回相反的结果:

struct P {
    const P * s = nullptr;
    constexpr P() {}
    constexpr P(const P & p) : s(&p) {
        if (s == this) throw 0; // never happens
    }
    constexpr bool operator()() const {
        return s != this; // shall be always true?
    }
};

constexpr bool f(P p) {
    return p.s ? p() : f(p);
}

int main() {
    static_assert( f(P{}) ); // fails in MSVC, where static_assert( f(P{}) == false );
}

在线演示:https://gcc.godbolt.org/z/nqYoshExj

如何解释相同的检查在对象的构造函数中传递,但在其方法中失败?

c++ visual-c++ c++17 constexpr copy-constructor
1个回答
0
投票

这肯定是msvc中的一个bug。

msvc(但不是 clang 或 gcc)对此断言也有同样的问题:

constexpr bool g(int x, void* s = nullptr) {
    if (s) return &x != s;
    return g(x,&x);
}

分解出递归(只能是 1 级深度),msvc 也接受断言:

constexpr bool h(int x, void* s) {
    return &x != s;    
}

constexpr bool h2(int x) {
    return h(x,&x);
}

现场演示

对代码进行相同的重构具有相同的效果(https://gcc.godbolt.org/z/69b57TPd8)。

© www.soinside.com 2019 - 2024. All rights reserved.