美文网首页
C++11 模板元编程 - 测试断言

C++11 模板元编程 - 测试断言

作者: MagicBowen | 来源:发表于2016-09-16 09:20 被阅读559次

    测试最重要的是要有断言。C++标准支持的编译期断言只有一个:static_assert

    static_assert是C++11标准引入的一个新关键字,用于在编译期做静态断言。它需要两个参数,第一个是一个可以在编译期返回bool值的常量表达式,第二个是一个字符串常量,用于当断言失败时编译器输出用。

    static_assert(sizeof(int) < 1, "Invoke an assertion failure!");
    

    当编译器编译到如上代码时会产生一个编译错误,在错误报告中会包含字符串“Invoke an assertion failure!”。

    在前面的介绍中,我们已经将模板元编程的计算对象和返回结果都统一成类型了,所以我们需要对static_assert进行封装,让其能够直接对类型进行断言。

    首先我们需要一个断言ASSERT_TRUE(),它可以针对返回BoolType的元编程表达式进行断言。例如可以如下使用:

    ASSERT_TRUE(__bool(true));
    ASSERT_TRUE(__not(__false()));
    ASSERT_FALSE(__or(__true(), __false()));
    

    我们需要用static_assert实现ASSERT_TRUE,就需要对ASSERT_TRUE的入参调用__value()元函数求值。如下是ASSERT_TRUE的实现:

    // "tlp/test/details/Asserter.h"
    
    #define ASSERT_TRUE(T)                  \
    static_assert(__value(T), "Assert Failed: expect "#T" be true, but be false!")
    

    同样我们实现ASSERT_FALSE如下:

    // "tlp/test/details/Asserter.h"
    
    #define ASSERT_FALSE(T)                 \
    static_assert(!(__value(T)), "Assert Failed: expect "#T" be false, but be true!")
    

    接下来我们实现用于断言两个类型是否相等的ASSERT_EQ()ASSERT_NE()

    // "tlp/test/details/Asserter.h"
    
    #define ASSERT_EQ(T, Expected)          \
    static_assert(__value(__is_eq(T, Expected)), "Assert Failed: expect "#T" be equal to "#Expected"!")
    
    #define ASSERT_NE(T, Expected)          \
    static_assert(!(__value(__is_eq(T, Expected))), "Assert Failed: expect "#T" be not equal to "#Expected"!")
    

    它们的用法如下:

    ASSERT_EQ(__int(0), __int(0));
    ASSERT_NE(__int(0), __int(1));
    ASSERT_EQ(__if(__true(), int, char), int);
    ASSERT_EQ(__if(__false(), int, char), char);
    

    TLP库中有一个特殊的类型NullType,它的定义如下:

    // "tlp/base/NullType.h"
    
    struct NullType;
    
    #define __null() NullType
    

    NullType仅有类声明,所以不能实例化。NullType被TLP库用于各种计算返回的无效值中。对此有一个元函数__valid()专门用于判断表达式的值是否为NullType。

    template<typename T>
    struct Valid
    {
        using Result = __true();
    };
    
    template<>
    struct Valid<NullType>
    {
        using Result = __false();
    };
    
    #define __valid(...)    typename Valid<__VA_ARGS__>::Result
    

    当然你也可以对其扩展,通过定义Valid的不同特化,来支持更多的错误类型。

    对此,TLP提供了断言ASSERT_VALIDASSERT_INVALID,专门用于判断表达式是否有效:

    // "tlp/test/details/Asserter.h"
    
    #define ASSERT_VALID(T)                 \
    static_assert(__value(__valid(T)), "Assert Failed: expect "#T" be valid, but be invalid!")
    
    #define ASSERT_INVALID(T)               \
    static_assert(!(__value(__valid(T))), "Assert Failed: expect "#T" be invalid, but be valid!")
    

    测试用例

    返回 C++11模板元编程 - 目录

    相关文章

      网友评论

          本文标题:C++11 模板元编程 - 测试断言

          本文链接:https://www.haomeiwen.com/subject/zstiettx.html