我有一种感觉,Expects 有点违背 C++ 的精神(正如我所理解的这种精神)......如果 C++ 更主流和类似 Java 可能真的很好,但对我来说,它最初的想法是提供最大性能(有时以降低安全性/增加复杂性/降低可读性为代价)。我认为我们可以在不牺牲性能的情况下实现这两个目标。对我来说,解决方案非常简单 - 自定义断言 (cassert) - 这是可以为发布版本打开或关闭的快速断言。
示例实现(仅限 Windows):
// cassert.h:
#pragma once
// Switch this macro off for maximum performance release builds:
#define __RELEASE_WITH_ASSERTS__
#ifndef cassert
#if defined(_DEBUG) || defined(__RELEASE_WITH_ASSERTS__)
void __cassert(bool val, const char* szFile, int line, const char* szDesc);
#define cassert(a) ((a) ? ((void)1) : __cassert(a, __FILE__, __LINE__, _CRT_STRINGIZE(#a)))
#else
#define cassert(a)
#endif
#endif
// cassert.cpp
#if defined(_DEBUG) || defined(__RELEASE_WITH_ASSERTS__)
void __cassert(bool val, const char* szFile, int line, const char* szDesc)
{
if (!val)
{
std::string sIgnore;
int mode;
#if defined(_DEBUG)
sIgnore = "\n\nIgnore assertion?";
mode = MB_YESNO;
#else
sIgnore = "";
mode = MB_OK;
#endif
char szLine[16];
_itoa(line, szLine, 10);
std::string sAssertion = std::string("Assertion failed in file ") + szFile + " at line " + szLine + "\n" + szDesc;
Log(sAssertion.c_str());
if (MessageBoxA(NULL, (std::string("Assertion failed in file ") + szFile + " at line " + szLine + "\n" + szDesc + sIgnore).c_str(), "Assertion failed", mode | MB_ICONINFORMATION) == IDNO)
_CrtDbgBreak();
}
}
#endif
这样的 cassert 甚至会使调试构建运行得更快,因为如果条件满足,则没有对 (c)assert 函数的实际调用(并且每个这样的调用都会非常繁重,因为 _CRT_STRINGIZE(#a) (条件为字符串)。