如何对模板代码的故意编译错误进行单元测试

Unc*_*eiv 39 c++ templates unit-testing

请注意,这不是如何编写单元测试来验证编译错误?因为我不关心测试外部库或编译器本身的正确性.

它在C++中是典型的,特别是在处理模板时,采用阻止某些特定代码编译的技术.由于这些问题可能会变得复杂,确保特定代码片确实会产生编译器错误的最佳方法是什么?

由于测试甚至不应该编译,你不能依赖诸如东西,所以我想它应该集成在构建系统中?这些问题通常如何处理?

Jan*_*dec 11

以类似的方式编写编译器测试.您将在某些脚本语言(shell,perl,tcl等)中使用一些测试代码,这些代码将在给定的代码片段上运行编译器,并检查是否编译了正确的代码,而正确的代码则没有.

  • gcc使用DejaGnu,它建立在expect之上,它本身构建在Tcl之上.
  • 如果你使用shell脚本(可能更容易,DejaGnu可能有点过分),你可能想看一下shUnit2.
  • Perl的Test::Harness系统应该很容易使用.
  • 毕竟,从C++运行进程并没有那么多工作,所以编写一个函数来尝试在给定的字符串上调用编译器并检查它是否输出错误,你预期它不会那么难,你可以整合它进入其他基于boost.test的测试.


mut*_*oid 5

测试 a negative feature,因此可以使用以下c++20 requires表达式来保证某些构造将无法编译:

简单的例子

下面,我检查func静态断言中是否存在该函数的重载,当与测试框架一起使用时,应该在运行时测试之一上使用布尔值,以免阻止其他测试编译:

#include <concepts>
/// Arbitrary restrictions in order to test:
/// if T != double -> zero args
template <typename T> void func(){};
/// if T == double -> arbitrary args.
template<std::same_as<double> ...T> void func(T... as){};
template <typename T, typename... a> constexpr bool applies_to_func = requires(a... as) {
  func<T>(as...);
};
/// compiles:
static_assert(applies_to_func<int>);
static_assert(applies_to_func<double, double>);
static_assert(applies_to_func<double, double, double>);
/// function fails to compile:
static_assert(!applies_to_func<int, int>);

Run Code Online (Sandbox Code Playgroud)

该代码可在编译器资源管理器上找到:https : //godbolt.org/z/direWo

C++17

我最近尝试为一个我只能使用 c++17 的项目做类似的事情。在我的代码中,我还检查函数的返回类型是否符合调用者的期望。除了非类型模板参数的一些限制外,还可以实现类似的事情,如下所示。在这种情况下,由于隐式转换,我无法执行 double 作为重载的输入,applies_to_func(void, int, int)将在下面的代码片段中评估为 true。

#include <concepts>
/// Arbitrary restrictions in order to test:
/// if T != double -> zero args
template <typename T> void func(){};
/// if T == double -> arbitrary args.
template<std::same_as<double> ...T> void func(T... as){};
template <typename T, typename... a> constexpr bool applies_to_func = requires(a... as) {
  func<T>(as...);
};
/// compiles:
static_assert(applies_to_func<int>);
static_assert(applies_to_func<double, double>);
static_assert(applies_to_func<double, double, double>);
/// function fails to compile:
static_assert(!applies_to_func<int, int>);

Run Code Online (Sandbox Code Playgroud)