5

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

错误:'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”发生的特定编译错误?

谢谢你的帮助!

PS 这是我的第一篇文章,希望我已经做了“足够”的研究,并正确地完成了其他所有工作。对不起,如果我没有。

4

5 回答 5

4

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

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

于 2012-03-29T00:50:17.470 回答
4

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

如果您想让它成为运行时错误,请将方法公开/使用朋友/无论您需要做什么来提供对某些内容的访问并在方法的定义中抛出异常,在调用代码中捕获并处理异常。

但是,我没有看到这样做的目的。总是更喜欢编译时错误而不是运行时错误。总是。

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

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

于 2012-03-29T01:03:05.737 回答
3

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

在你的测试文件中,把#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 进行编译才能使用这些函数中的大部分。

(如Assert that code doesn't compile中首先描述的)

于 2015-11-03T16:17:49.760 回答
3

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

我认为如果您可以使用C++2a.

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

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

简单的例子

下面,我检查了invalid_function不能在 Struct 类型上调用不存在的函数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.");

请注意,您可以将 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>);
}

该代码可在Compiler Explorer上找到。

用例

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

于 2020-03-26T10:08:34.280 回答
0

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

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

于 2012-03-29T00:51:43.127 回答