断言当 X 为真时 Y 也为真 - 暗示

assert when X is true Y is true too - implication

本文关键字:暗示 断言      更新时间:2023-10-16

如何断言如果Xtrue那么Y也是true。问题是,如果我写以下内容:

assert(X && Y && "If X is true then Y should be true too.");

如果bool X = false;,将失败,而这也可能是有效的情况。

逻辑表达式为:assert(!X || (X && Y))

如果您希望包含您的消息,您可以将其括在括号中:

assert((!X || (X && Y)) && "If X is true then Y should be true too.");

现在,我们可以简化这个逻辑,因为我们知道,如果!X评估false(并且我们正在评估||的右侧),那么我们知道X一定是真的,所以我们可以进一步简化它:

assert(!X || Y); // If !X is false, then X must be true, so no need to test it.

如何断言如果X为真,那么Y也是为真

你所描述的是暗示:X → Y

C++中没有隐含运算符。但是,例如使用真值表证明该X → Y等同于¬X ∨ Y是微不足道的。我们可以用C++写,因为它同时具有否定和 OR 运算符(析取):

assert(!X || Y);
constexpr bool a_implies_b( bool a, bool b ) {
  return a?b:true;
}

然后:

assert(a_implies_b(X, Y) && "If X is true then Y should be true too.");

或者,如果你想玩得开心...

namespace implies_trick {
  struct lhs_t {
    bool v;
    constexpr lhs_t(bool b):v(b) {}
  };
  struct implies_t { constexpr implies_t() {} };
  constexpr implies_t implies = {};
  constexpr lhs_t operator->*( bool a, implies_t ) { return {a}; }
  constexpr bool operator*( lhs_t a, bool b ) { return a.v?b:true; }
}
using implies_trick::implies;
for (bool X:{true, false})
  for (bool Y:{true, false})
    std::cout << X << "->" << Y << " is " << X ->*implies* Y << "n";

活生生的例子。

这使您可以编写:

assert(X ->*implies* Y && "If X is true then Y should be true too.");

类似于Yakk的好答案,但语法不同:

#include <iostream>

namespace detail {
    struct when_impl
    {
        constexpr when_impl(bool condition)
        : _cond(condition)
        {}
        constexpr operator bool() const { return _cond; }
        bool _cond;
    };
    struct then_impl
    {
        constexpr then_impl(bool condition)
        : _cond(condition)
        {}
        constexpr operator bool() const { return _cond; }
        bool _cond;
    };
}
constexpr auto when(bool condition)
{
    return detail::when_impl(condition);
}
constexpr auto then(bool condition)
{
    return detail::then_impl(condition);
}
constexpr bool operator,(detail::when_impl when, detail::then_impl then)
{
    if (bool(when)) return bool(then);
    return true;
}
int main()
{
    for (bool X:{true, false})
        for (bool Y:{true, false})
            std::cout << X << "->" << Y << " is " << (when(X), then(Y)) << "n";
    static_assert((when(true), then(true)), "Y must follow X");
    return 0;
}

预期输出:

1->1 is 1
1->0 is 0
0->1 is 1
0->0 is 1

(注意:static_assert在构建过程中不会触发)