c++测试验证相等操作符随时间保持与结构体一致
C++ test to verify equality operator is kept consistent with struct over time
我投票给@TomalakGeretkal,因为他写了一篇关于合同的好文章;我还没有接受答案,因为我的问题是如何以编程方式检查相等函数。
我有一个POD结构&一个相等算子,一个(非常)小的部分,系统有>100个工程师。
随着时间的推移,我希望结构被修改(成员添加/删除/重新排序),我想写一个测试来验证相等性op正在测试结构的每个成员(例如随着结构的变化而保持最新)。
正如Tomalak指出的那样-评论&"通过合同"通常是执行这一点的最佳/唯一方式;然而,在我的情况下,我预计会出现问题,并希望探索是否有任何方法可以主动捕获(至少许多)修改。
我没有想出一个令人满意的答案——这是我想到的最好的答案:
-new up two instances struct (x, y), fill each with identical non-zero data.
-check x==y
-modify x "byte by byte"
-take ptr to be (unsigned char*)&x
-iterator over ptr (for sizeof(x))
-increment the current byte
-check !(x==y)
-decrement the current byte
-check x==y
如果相等运算符捕获了每个字节,则测试通过(注意:对此有一个警告-并非所有字节都用于编译器表示的x,因此测试必须'跳过'这些字节-例如硬代码忽略字节)
我建议的测试有明显的问题:(至少)"不关心"字节,并且在x中增加一个字节的类型可能不会导致该内存位置的变量的有效值。
有更好的解决方案吗?
(这应该无关紧要,但我使用VS2008, rtti是关闭的,googletest套件)
虽然用这样的自检来使代码"万无一失"很诱人,但根据我的经验,让自检本身万无一失是徒劳的。
保持简单,并使任何更改的效果本地化。在结构定义中写一个注释,明确表示如果结构为;然后,如果这失败了,这只是程序员的错。
我知道这对您来说似乎不是最优的,因为它在将来可能会导致用户错误,但实际上您无法绕过这一点(至少在不使您的代码变得非常复杂的情况下),通常最实用的方法是不麻烦。
我同意(并支持)Tomalak的回答。你不太可能找到一个万无一失的解决方案。尽管如此,一种简单的半自动方法是在相等操作符内验证预期的大小:
MyStruct::operator==(const MyStruct &rhs)
{
assert(sizeof(MyStruct) == 42); // reminder to update as new members added
// actual functionality here ...
}
这样,如果添加了任何新成员,assert将被触发,直到有人更新相等操作符。当然,这并非万无一失。(成员变量可能被替换为相同大小的东西,等等)尽管如此,它是一个相对简单的(一行断言),可以很好地检测错误情况。
我知道我肯定会被投反对票,但是…
如果一个模板等价函数接受一个int形参的引用,并且测试两个对象呢?相等函数将返回bool值,但会将size引用(int)增加sizeof(T)。
然后有一个大的测试函数,调用每个对象的模板并求和总大小——>将这个和与对象的大小进行比较。虚函数/继承等的存在可能会扼杀这个想法。
这实际上是一个很难在自测中正确解决的问题。
我能想到的最简单的解决方案是使用几个操作多种类型的模板函数,执行必要的转换、提升和比较,然后在外部单元测试中验证结果。当一个重大的变更被引入时,至少你会知道。
使用组合等方法比使用扩展/子类更容易维护/验证这些挑战。
同意Tomalak和Eric的观点。我用它来解决类似的问题。
除非定义了DEBUG,否则Assert不起作用,因此您可能会发布错误的代码。这些测试并不总是可靠地工作。如果结构中包含位字段,或者插入了由于编译器对齐字边界而占用空闲空间的项,则大小不会改变。因此,它们提供的价值有限。例如
struct MyStruct {
char a ;
ulong l ;
}
改为
struct MyStruct {
char a ;
char b ;
ulong l ;
}
两个结构都是8字节(在32位Linux x86上)
- 根据用户回答声明"Players"。用户选择玩家数量。播放器是结构体
- 结构体 S { int align; } 之间的区别;(struct 关键字后的名称)和 struct { int al
- C++ - 如何在结构向量中找到结构体一个成员的最大值?
- 包含 std::list 的结构体的 C++ 初始化
- 结构体和类的不同大小(),彼此具有相同的字段类型
- 如何使用结构体的向量数组?
- 如何使用结构体在C++中更改这些代码?
- 无法在 Mosquitto MQTT Broker 插件上访问结构体 mosquitto 的元素
- 我应该如何在C++中使用结构体解决输入失败的问题?
- Qsort() 比较结构体整数的总和
- 如何使用迭代器指向结构体c++的向量
- 在C++中使用链表的堆栈实现中,访问结构体headNode成员count和top会导致运行时错误
- 如何获取结构体成员的地址
- 创建结构体向量,表达式:向量下标超出范围
- boost::任何带有结构体和无符号整数
- 如何在构造函数中初始化结构体的动态数组?
- 只写结构体的某些字段
- C++ push_back() 一个结构体到一个向量中
- C++14 结构体上的统一初始化
- 给定一个微秒值,如何准确地得到一个时间值结构体?/*更新获取负值*/