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


测试最重要的是要有断言。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模板元编程 - 目录

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,953评论 19 139
  • 简介 C++98/03的设计目标:一、比C语言更适合系统编程(且与C语言兼容)。二、支持数据抽象。三、支持面向对象...
    认真学计算机阅读 10,722评论 0 53
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 32,654评论 18 399
  • JAVA面试题 1、作用域public,private,protected,以及不写时的区别答:区别如下:作用域 ...
    JA尐白阅读 4,878评论 1 0
  • 小编费力收集:给你想要的面试集合 1.C++或Java中的异常处理机制的简单原理和应用。 当JAVA程序违反了JA...
    八爷君阅读 10,204评论 1 114

友情链接更多精彩内容