代码之家  ›  专栏  ›  技术社区  ›  Baiyan Huang

有没有一种方法可以对文本表达式和函数调用进行静态断言?

c++
  •  0
  • Baiyan Huang  · 技术社区  · 5 年前

    #define ASSERT_EQUAL(expected, actualFunc, desc)
    

    expected 应该是第一个参数,并且是文字; actualFunc 应该是第二个参数,并且是带参数的函数调用,示例调用如下所示:

    ASSERT_EQUAL(true, test1(42), "cache-friendly");
    

    在这个宏中,我还将对第二个参数(函数调用)计时,为了确保它按预期工作,我需要确保参数按正确的顺序传递,否则会出错,如下所示:

    ASSERT_EQUAL(test1(42), true, "cache-friendly");
    

    static_assert(std::is_fundamental<decltype(expected)::value)
    

    但它不起作用,因为即使我作为第一个参数传入函数调用,它也不会出错 预期 ,因为其返回值是基本类型。

    仅供参考-宏观实施:

    static int CaseNum = 0;
    
    #define ASSERT_BASE(expected, actualFunc, desc) \
      std::chrono::steady_clock clock;  \
      auto start = clock.now();  \
            auto actual = actualFunc; \
      auto elapsedTime = clock.now() - start; \
      auto timeInUS = std::chrono::duration_cast<std::chrono::microseconds>(elapsedTime).count(); \
      cout << boolalpha << "CASE " << ++CaseNum << ": " << "EXPECTED=" << expected  << "; ACTUAL=" << actual << "; elapsedTime=" << timeInUS << "us" <<  " --- " <<  desc << endl; \
    
    #define ASSERT_EQUAL(expected, actualFunc, desc) \
    { \
      ASSERT_BASE(expected, actualFunc, desc) \
      assert(expected == actual); \
    }
    
    #define ASSERT_NEAR(expected, actualFunc, desc) \
    { \
      ASSERT_BASE(expected, actualFunc, desc) \
      assert(fabs(expected - actual) < 0.0001); \
    }
    
    0 回复  |  直到 5 年前
        1
  •  2
  •   ecatmur    5 年前

    这是不可能的,通过检查语言内的表达式,因为C++不断地扩展在常量表达式中允许的范围。你可以检查一下 expected 可以用作常量表达式,例如,使用它初始化 constinit test 功能是 constexpr ,很可能是这样。

    static_assert(std::string_view{#expected}.find('(') == std::string_view::npos, "expected must be a literal");
    

    Example .

        2
  •  2
  •   Jarod42    5 年前

    我可能会建议另一种方法(不带宏)来强制第二个参数是函数/可调用的(而不是函数的结果):

    template <typename T, typename F>
    void AssertRun(T expected, F f, const std::string& descr)
    {
        static int CaseNum = 0;
    
        std::chrono::steady_clock clock;
        const auto start = clock.now();
        auto actual = f();
        const auto elapsedTime = clock.now() - start;
        const auto timeInUS =
            std::chrono::duration_cast<std::chrono::microseconds>(elapsedTime).count();
        std::cout << boolalpha << "CASE " << ++CaseNum << ": "
                  << "EXPECTED=" << expected
                  << "; ACTUAL=" << actual
                  << "; elapsedTime=" << timeInUS << "us"
                  <<  " --- " << desc << std::endl;
        return actual;
    }
    
    template <typename T, typename F>
    void AssertEqual(T expected, F f, const std::string& descr)
    {
        auto actual = AssertRun(expected, f, descr);
        assert(expected == actual);
    }
    

    然后

    AssertEqual(true, []{ return test1(42); }, "cache-friendly");
    

    AssertEqual(test1(42), []{ return true; }, "cache-friendly");