我是一名学生,我正在尝试编写并运行一些测试代码,以便在我将其打开之前对其进行检查。我现在要做的是测试我的代码是否正确地阻止了值语义。在我的作业中,我已经为每个类声明了自己的私有复制构造函数和赋值运算符,它们没有定义,所以什么都不做。在我的测试程序中调用它们时,我收到的编译错误就像我预期的那样。像这样:
错误:'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 ++中原生地测试某些编译错误(对于大多数语言来说,这可能是正确的,现在我想到了它)。我读了一个post,建议用脚本语言编写一些测试代码,试图编译C ++代码片段并检查是否有错误,另一个post建议使用Boost.Build。
做我想做的最简单/最好的方法是什么?
我查看了Boost.Build的文档,这有点过头了。如果我使用它,我将如何测试一个文件,比如'test.cpp'编译,并且可能处理'test.cpp'发生的特定编译错误?
感谢您的帮助!
P.S。这是我的第一篇文章,希望我做了“足够多”的研究,并做了其他一切正确的事情。对不起,如果我没有。
答案 0 :(得分:3)
try-catch在运行时发生,而编译器静态尝试链接您在编译时调用的函数,因此编译将始终失败。
或者,如果您愿意使用C ++异常,那么您可以实现复制和赋值方法,将它们公之于众,并在这些函数的主体中抛出异常。请注意,在基本上每种情况下,如果您有选择,则应优先选择静态/编译时检查而不是运行时检查。
答案 1 :(得分:3)
这些是编译器错误,而不是例外。异常是程序员抛出运行时错误并捕获/处理它们的机制。编译器甚至无法为您运行构建可执行文件,因为它识别代码格式错误且是无效的C ++代码。
如果你想让它成为运行时错误,那么让方法公共/使用朋友/你需要做什么来提供对某些东西的访问并在方法的定义中引发异常,catch和处理异常调用代码。
然而,我没有看到这样做的目的。始终更喜欢编译时错误到运行时错误。总是
C ++标准定义了什么是有效代码或无效代码,有些东西是未定义的,其他东西留给实现编译器的人。任何符合标准的C ++编译器都会产生错误,因为某些内容不符合标准/定义,因此无效。错误通常是说某些事情含糊不清或直言不讳,你需要修改你所写的内容。
运行时错误要么是崩溃,要么是从用户的角度来看是无意的和不需要的行为。编译器错误是编译器说“我不明白你在说什么。这没有意义。”。编译器警告是编译器说“我会让你这样做,但我可能不应该。你真的确定这是你的意思吗?”。
答案 2 :(得分:2)
进行了更多研究之后,似乎没有(简便)的方法可以在C ++中本地测试某些编译错误
我认为如果可以使用C++2a
,情况可能就不再如此。
由于我目前正在为模板代码编写测试,所以我也尝试测试编译时错误。
尤其是,我想测试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上可用。
我将其用于模板元编程,以确保代码符合某些理论约束。
答案 3 :(得分:1)
你真正想要测试的不是编译器失败,而是你想测试关于你的类的某些假设。
在测试文件中,添加#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编译才能使用大多数这些函数。
(如[{3}}中所述)
答案 4 :(得分:0)
无法抑制这种编译错误。它们是C ++标准的错误。
当然,你可以在你自己的(或修补过的)编译器中压制它们中的一些。