下面的程序已尽可能地缩减,以显示 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
如何解释同样的检查在对象的构造函数中通过,但在其方法中却失败了?
这肯定是 msvc 的一个错误。
msvc(但不是 clang 或 gcc)对此断言有同样的问题:
考虑到递归(它只能是 1 级深度),msvc 也接受断言:
现场演示
对您的代码进行相同的重构具有相同的效果(https://gcc.godbolt.org/z/69b57TPd8)。