C++测试编译错误

C++ testing for compile errors

本文关键字:错误 编译 测试 C++      更新时间:2023-10-16

我是一名学生,我正在为作业编写并运行一些测试代码,以便在交作业之前对其进行检查。我现在要做的是测试我的代码是否正确地阻止了值语义。在我的赋值中,我为我的每个类声明了它自己的private复制构造函数和赋值运算符,它们没有定义,所以什么也不做。当它们在我的测试程序中被调用时,我会像预期的那样出现编译错误。类似这样的东西:

错误:"myClass::myClass(const&myClass)"是私有的""

错误:'myClass&myClass::operator=(const myClass&)'是专用

有没有一种方法可以使用try/catch来编译和运行我的测试代码,但向我表明这些错误确实发生了?我试过:

myClass obj1(...);
myClass obj2(...);
try{
  obj1 = obj2;
  throw 1;
}
catch(int e){
  assert(e==1);
}

但是编译器仍然给我上面的错误。这些不是"例外"吗?他们不会触发投掷吗?

如果我正确理解try/catch,它会处理运行时错误,而不是我上面看到的那种错误,对吗?

在做了更多的研究之后,似乎没有(简单的)方法来测试C++中的某些编译错误(现在我想起来了,这可能对大多数语言都是正确的)。我读过一篇文章,建议用脚本语言编写一些测试代码,尝试编译C++代码片段并检查是否有任何错误,还有一篇文章建议使用Boost.Build.

做我想做的事情最简单/最好的方法是什么?

我看了Boost.Build的文档,有点不知所措。如果我使用它,我将如何测试一个文件,比如"test.cpp"编译,并可能处理"test.cpp'"出现的特定编译错误?

谢谢你的帮助!

附言:这是我的第一个帖子,希望我已经做了";足够的";研究,其他一切都做得很好。对不起,如果我没有。

这些是编译器错误,而不是异常。异常是程序员抛出运行时错误并捕获/处理它们的一种机制。编译器甚至无法生成可执行文件供您运行,因为它识别出代码格式错误并且是无效的C++代码。

如果您想将其设为运行时错误,请将该方法设为public/use friends/无论您需要做什么来提供对某些内容的访问,并在方法的定义中抛出异常,在调用代码中捕获并处理异常。

然而,我认为这样做没有任何意义。总是喜欢编译时错误而不是运行时错误。总是

C++标准定义了什么是有效的或无效的代码,有些东西是未定义的,而其他东西则由实现编译器的人决定。任何符合标准的C++编译器都会出现错误,因为某些内容不符合标准/定义,因此是无效的。错误通常是说有些东西模棱两可或毫无意义,你需要修改你写的东西。

运行时错误要么是崩溃,要么是从用户的角度来看是无意的和不需要的行为。编译器错误是编译器说"我不明白你在说什么。这没有意义。"。编译器警告是编译器说:"我会让你这么做,但我可能不应该。你真的确定这是你的意思吗?"。

try-catch发生在运行时,而编译器静态地尝试链接您在编译时调用的函数,因此编译总是会失败。

或者,如果您愿意使用C++异常,那么您可以只实现复制和赋值方法,将它们公开,并在这些函数的主体中抛出异常。请注意,基本上在所有情况下,如果可以选择的话,您应该更喜欢静态/编译时检查而不是运行时检查。

在做了更多的研究之后,似乎没有(简单的)方法来测试C++中的某些编译错误

我认为,如果您可以使用C++2a,情况可能不再如此。

由于我目前正在为模板化代码编写测试,我还尝试测试编译时的错误。

特别是,我想测试negative feature,从而保证某些构造将无法编译。使用如下c++20 requires表达式,这是可能的:

简单示例

下面,我检查不存在的函数invalid_function不能在类型为S:的结构上调用

struct S {}; //< Example struct on which I perform the test
template <typename T> constexpr bool does_invalid_function_compile = requires(T a) {
  a.invalid_function();
};
static_assert(!does_invalid_function_compile<S>, "Error, invalid function does compile.");

请注意,您可以用测试框架的appropriate函数来替换static_assert,该函数在运行时记录测试错误,从而避免使用此编译测试来阻止其他测试的执行。

表单问题示例

当然,这个例子可以适用于问题中描述的场景,可能大致如下:

/// Test struct with deleted assignment operator
struct myClass {
  auto operator=(myClass const &) = delete;
};
/// Requires expression which is used in order to check if assigment is possible
template <myClass cl1, myClass cl2> constexpr bool does_assignment_compile = requires() {
  cl1 = cl2;
};

int main() {
  myClass cl1;
  myClass cl2;
  // Note that static assert can only be used if this can be known at compile time. Otherwise use
  // the boolean otherwise.
  static_assert(!does_assignment_compile<cl1, cl2>);
}

该代码可在编译器资源管理器上获得。

用例

我将其用于模板元编程,以确保代码符合某些理论约束。

您真正想要测试的不是编译器失败,而是您想要测试关于类的某些假设。

在测试文件中,放入#include <type_traits>

然后添加

assert((std::is_assignable <myClass, myClass> ::value) == FALSE);
assert((std::is_copy_assignable<myClass> ::value) == FALSE);
assert((std::is_copy_constructible<myClass> ::value) == FALSE);

这里记录了您可以检查的各种特征:http://en.cppreference.com/w/cpp/types

请注意,您必须为C++11进行编译才能使用这些函数中的大部分。

(如断言代码不编译中首先描述的)

这种编译错误是无法抑制的。从C++标准的角度来看,它们是错误的。

当然,您可以在自己的(或修补的)编译器中压制其中一些。