c++ - 包装代码以避免重复的技术?

标签 c++ macros

我在测试用例中使用了以下 C++ 代码来强制异常并增加覆盖范围:

    bool exceptionThrown(false);

     try {

         /* One or multiple lines of code */

     } catch (std::runtime_error& e) {
         std::cerr << "    Exception caught: " << e.what() << "\n";
         exceptionThrown = true;
     }

     if (exceptionThrown) {
         std::cerr << "    OK: Exception has been thrown\n";
     } else {
         std::cerr << "    FATAL: Exception should have been thrown\n";
         return(1);
     }

正如你所想象的,随着测试数量的增加,这段代码会重复很多,这是我根本不喜欢的。我一直在考虑一种用例如来包装这段代码的方法宏,但我不确定这是否是一个好的做法。在这种情况下,您有什么建议可以避免代码重复吗?

最佳答案

除了“为什么不使用谷歌测试?”之类的明显问题之外和“为什么不使用 boost 测试框架?”等等

这里有一种方法可以做你想做的事: (编辑:更新以减少测试主体中的输入 - 该版本是单线程的,一个简单的修改可以使其线程安全)

#include <iostream>
#include <stdexcept>

namespace detail {
    struct try_base {
        virtual ~try_base() = default;
        virtual const std::string& message() const = 0;

        static std::unique_ptr<try_base>& last() {
            struct empty : try_base {
                const std::string& message() const override { return _message; }
                std::string _message = "no exception";
            };
            static std::unique_ptr<try_base> _p = std::make_unique<empty>();
            return _p;
        }

        bool threw() const { return _threw; }
        operator bool() const { return !threw(); }
        bool operator!() const { return threw(); }

        bool _threw = false;
    };

    template<class F, class...Args>
    struct try_exec
    : try_base {
        try_exec(F&& f, Args&&...args)
        {
            try {
                f(std::forward<Args>(args)...);
            }
            catch(const std::exception& e) {
                _threw = true;
                _message = e.what();
            }
        }

        const std::string& message() const override { return _message; }

        std::string _message;

    };
}

template<class F, class...Args>
const auto& try_exec(F&& f, Args&&... args)
{
    auto& last = detail::try_base::last();
    last = std::make_unique<detail::try_exec<F, Args...>>(std::forward<F>(f),
                                                          std::forward<Args>(args)...);
    return *last;
}

bool report()
{
    std::cout << detail::try_base::last()->message() << std::endl;
    return true;
}

void example2(int x, int y)
{
    using namespace std;
    if (x < 6) {
        throw std::logic_error("example 2 throws with "s + to_string(x) + " and " + to_string(y));
    }
}

auto main() -> int
{
    try_exec([] {
        throw std::runtime_error("foo");
    }) or report();

    try_exec(&example2, 5, 4) or report();

    try_exec([]{
        example2(5, 4);
    }) or report();



    return 0;
}

预期输出;

test 1 threw: foo
test 2 threw: example 2 throws with 5 and 4
test 3 threw: example 2 throws with 5 and 4

关于c++ - 包装代码以避免重复的技术?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33516521/

相关文章:

c++ - 对成员函数使用 std::function

C++,二维 vector 分割错误

使用 ## 和 __LINE__ 创建 C 宏(与定位宏的标记串联)

scala - 如何在Scala控制台中使用宏?

c++ - 访问多映射 C++ 中的元素

javascript - C++ - IWebBrowser2 - Javascript 未激活

sql-server - 将 exec sp_executesql 转换为普通查询的简单方法?

用于创建查找表的 C 预处理器宏

clojure - 我可以在 Clojure 的宏中引用宏吗?

C++ vector 和错误 "no instance of overloaded function"