c++11 boost - 断言

2018-07-11 21:39:09

运行时断言

c/c++ 标准里提供了 assert 宏,只能用于简单的断言,判断是否为真。

assert 库能提供更强大的断言,下面定义了两个宏

#define BOOST_ASSERT(expr) assert(expr)
#define BOOST_ASSERT_MSG   assert((expr)&&(msg))
//禁用 boost 断言
#define BOOST_DISABLE_ASSERTS

//启用宏控制句柄
#define BOOST_ENABLE_ASSERT_HANDLER

一旦启用了宏控制句柄,就可以为断言提供一个错误处理 handler。

因为断言会终止程序,所以下面的例子自己改动测试。

// Copyright (c) 2015
// Author: Chrono Law
#include <cstring>
#include <cassert>
#include <iostream>
using namespace std;

//#define BOOST_DISABLE_ASSERTS
//#define BOOST_ENABLE_ASSERT_HANDLER   //启用宏控制句柄
#include <boost/assert.hpp>

double func(int x)
{
    BOOST_ASSERT_MSG(x != 0, "divided by zero");
    return 1.0 / x;
}

double func2(int x)
{
    BOOST_ASSERT(x != 0 && "divided by zero");
    cout << "after BOOST_ASSERT" << endl;

    assert(x != 0 && "divided by zero");
    cout << "after" << endl;

    return 1.0 / x;
}

void case1()
{
    BOOST_ASSERT(16 == 0x10);
    BOOST_ASSERT(string().size() == 1);

    func(0);
    func2(0);

    int len;
    BOOST_VERIFY(len = strlen("123"));
    assert(len == 3);
}

//////////////////////////////////////////

#include <boost/format.hpp>
namespace boost {
void    assertion_failed(char const*, char const*, char const*, long) {}
void assertion_failed_msg(char const * expr, char const * msg, 
                        char const * function, 
                        char const * file, long line)
{
    boost::format fmt("Assertion failed!\nExpression: %s\n"
                      "Function: %s\nFile: %s\nLine: %ld\n"
                      "Msg: %s\n\n");
    fmt % expr% function% file% line %msg;
    cout << fmt;
}
}

int main()
{
    case1();
}


编译时断言

static_assert 主要在泛型编程或模板元编程中用于验证编译期常数或者模板类型参数,读者目前可能用不到。

// Copyright (c) 2015
// Author: Chrono Law
#include <iostream>
using namespace std;

#include <boost/static_assert.hpp>

void case1()
{
    BOOST_STATIC_ASSERT(2 == sizeof(short));
    BOOST_STATIC_ASSERT(true);
    BOOST_STATIC_ASSERT_MSG(16 == 0x10, "test static assert");
}

template<typename T>
T my_min(T a, T b)
{
    BOOST_STATIC_ASSERT_MSG(sizeof(T) < sizeof(int), "only short or char");
    return a < b? a: b;
}
void case2()
{
    cout << my_min((short)1, (short)3);
    //cout << my_min(1L, 3L);
}

namespace my_space
{
    class empty_class
    {
        BOOST_STATIC_ASSERT_MSG(sizeof(int)>=4, "for 32 bit");
    };

    BOOST_STATIC_ASSERT(sizeof(empty_class) == 1);
}


int main()
{
    case1();
    case2();
}


lightweight_test 是一个轻量级的单元测试框架,不支持测试用例、测试套件的概念,但是因为简单,所以适合要求不高或快速的测试工作。

下面是一些常用的测试断言

#define BOOST_TEST(expression) /*测试成立*/
#define BOOST_TEST_NOT(expression) /*测试不成立*/
#define BOOST_ERROR(message) /*直接断言失败*/
#define BOOST_TEST_EQ(expr1, expr2) /*相等*/
#define BOOST_TEST_NE(expr1, expr2) /*不等*/
#define BOOST_TEST_LT(expr1, expr2) /*小于*/
#define BOOST_TEST_LE(expr1, expr2) /*小于等于*/
#define BOOST_TEST_GT(expr1, expr2) /*大于*/
#define BOOST_TEST_GE(expr1, expr2) /*大于等于*/
#define BOOST_TEST_CSTR_EQ(expr1, expr2) /*c字符串相等*/
#define BOOST_TEST_CSTR_NE(expr1, expr2) /*c字符串不等*/
#define BOOST_TEST_THROWS(expr, excep) /*断言表达式expr,抛出异常excep*/

如果断言失败都会增加内部的错误计数,boost::report_errors()会输出测试结果。

// Copyright (c) 2015
// Author: Chrono Law
#include <type_traits>
using namespace std;

#include <boost/smart_ptr.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
//using namespace boost;

int main()
{
    auto p = make_shared<int>(10);

    BOOST_TEST(*p == 10);
    BOOST_TEST(p.unique());
    BOOST_TEST_NOT(!p);

    BOOST_TEST_EQ(p.use_count(), 1);
    BOOST_TEST_NE(*p, 20);

    p.reset();
    BOOST_TEST(!p);

    BOOST_TEST_THROWS(*p, std::runtime_error);
    BOOST_ERROR("error accured!!");
	
	//元编程的有限支持
    BOOST_TEST_TRAIT_TRUE((is_integral<int>));
    BOOST_TEST_TRAIT_FALSE((is_function<int>));

    return boost::report_errors();
}
[root@192 c++]# g++ -std=c++11 main.cpp -g
[root@192 c++]# ./a.out 
main.cpp(25): Exception 'std::runtime_error' not thrown in function 'int main()'
main.cpp(26): error accured!! in function 'int main()'
2 errors detected.

test 库最小化测试,只需要包含头文件 <boost/test/minimal.hpp>就可以使用。 入口函数 mInimal test内部已经实现了main(),因此我们不必再编写自己的main(),只需要实现一个 test_main()函数,它是minimal test的真正功能函数。

 minimal test提供四个测试断言宏,比较简单:

BOOST_CHECK(e):断言测试通过,如不通过不影响程序执行;
BOOST_REQUIRE(e):要求测试必须通过,否则程序停止执行;
BOOST_ERROR(s):给出一个错误信息,程序继续执行;
BOOST_FAIL(S):给出一个错误信息,程序运行终止;

#include <iostream>
using namespace std;

#include <boost/format.hpp>
#include <boost/test/minimal.hpp>

int test_main( int argc, char* argv[] )
{
    using namespace boost;
    format fmt("%d-%d");

    BOOST_CHECK(fmt.size() == 0);
    fmt % 12 % 34;
    BOOST_REQUIRE(fmt.str() == "12-34");

    //BOOST_ERROR("演示一条错误消息");

    fmt.clear();
    fmt % 12;
    try
    {
        std::cout << fmt;  //输入参数不完整,抛出异常
    }
    catch (...)
    {
        BOOST_FAIL("致命错误,测试终止");
    }
    return 0;
}
[root@192 c++]# g++ -std=c++11 main.cpp -g
[root@192 c++]# ./a.out 
main.cpp(12): test fmt.size() == 0 failed in function: 'int test_main(int, char**)'

**** 1 error detected


 备注

1.编译器版本gcc4.8.5,运行环境centos7 64位
2.本文只做简单记录用,详细用法请参考 Boost Library,或者是罗剑锋的 boost程序库完全开发指南 书本
3..原文地址http://www.freecls.com/a/2712/a4


©著作权归作者所有
收藏
推荐阅读
简介
天降大任于斯人也,必先苦其心志。